/**
 * Server-authoritative "may this session click-to-dial?" gate.
 *
 * Rule: the logged-in user must be AD_User.IsSystemUser = 'Y' AND have a
 * non-empty AD_User.SIP_Extension. Both live only in iDempiere (the trimmed
 * logship_user cookie carries neither — and in the app build that cookie is
 * client-supplied anyway), so the identity comes from the JWT in logship_it and
 * the flags from models/ad_user/{id}. Verdicts are cached 10 min per user;
 * the user update route calls invalidateDialer() when the extension changes.
 *
 * Fail-closed: any lookup error → canDial:false (never throws to the route).
 */
import { decodeJwt } from '../chatAccess'
import refreshTokenHelper from '../refreshTokenHelper'

const TTL_MS = 10 * 60 * 1000

export interface DialerInfo {
  userId: number
  name: string
  extension: string
  isSystemUser: boolean
  canDial: boolean
  orgId: number
}

const g = globalThis as any
const cache: Map<number, { info: DialerInfo; expires: number }> =
  g.__dialAccessCache ?? (g.__dialAccessCache = new Map())

export const invalidateDialer = (userId: number) => { cache.delete(Number(userId)) }

const truthy = (v: any) => v === true || v === 'Y' || v === 'true'

const fetchUser = async (userId: number, token: string) => {
  const config = useRuntimeConfig()
  return await $fetch<any>(`${config.api.url}/models/ad_user/${userId}`, {
    headers: { Authorization: 'Bearer ' + token, Accept: 'application/json' },
    retry: 0,
    timeout: 15000
  })
}

/** Digits only, max 10 — an extension is never anything else. */
export const cleanExtension = (v: any): string => String(v ?? '').replace(/\D+/g, '').slice(0, 10)

export const resolveDialer = async (event: any): Promise<DialerInfo | null> => {
  const token = getCookie(event, 'logship_it')
  if (!token) return null
  let userId = 0
  try { userId = Number(decodeJwt(token)?.AD_User_ID) } catch { return null }
  if (!userId) return null

  const hit = cache.get(userId)
  if (hit && hit.expires > Date.now()) return hit.info

  const build = (user: any): DialerInfo => {
    const isSystemUser = truthy(user?.IsSystemUser ?? user?.isSystemUser)
    const extension = cleanExtension(user?.SIP_Extension ?? user?.sip_Extension ?? user?.sIP_Extension)
    return {
      userId,
      name: String(user?.Name || user?.name || ''),
      extension,
      isSystemUser,
      canDial: isSystemUser && extension.length > 0,
      orgId: Number(user?.AD_Org_ID?.id || 0)
    }
  }

  try {
    let user: any
    try {
      user = await fetchUser(userId, token)
    } catch (err: any) {
      const status = Number(err?.status || err?.statusCode || err?.response?.status || 0)
      if (status !== 401 && status !== 403) throw err
      const fresh = await refreshTokenHelper(event)
      user = await fetchUser(userId, fresh)
    }
    const info = build(user)
    cache.set(userId, { info, expires: Date.now() + TTL_MS })
    return info
  } catch (err: any) {
    console.warn('[dial] dialer lookup failed for user', userId, '-', err?.data?.message || err?.message || err)
    return null
  }
}
