import { toast } from 'bulma-toast'

/**
 * Click-to-dial (FreePBX/Asterisk) client gate + action.
 *
 * `capability` is resolved ONCE per session from /api/telephony/me (server-
 * authoritative: system user + SIP_Extension) and shared through useState, so
 * the many <DialButton>s on a page cost no extra requests. `dial()` POSTs to
 * /api/telephony/dial, which returns as soon as the PBX accepted the call —
 * the user's own phone rings first, then the target is dialed.
 */
export interface DialCapability {
  loaded: boolean
  enabled: boolean
  canDial: boolean
  extension: string | null
}

export interface DialTarget {
  number: string
  /** AD_User the number belongs to → the call activity is written on this user. */
  userId?: number | string | null
  /** Fallback: C_BPartner → the activity goes to the partner's first contact user. */
  partnerId?: number | string | null
  /** Display name shown on the agent's phone + in the activity. */
  label?: string | null
  /** Per-call extension override (dial popover chooser); default = the user's own. */
  extension?: string | null
}

export interface DirectoryExtension { ext: string; state: string; stateLabel: string; pbxName: string; name: string; userId: number | null; isMine: boolean }

/** Same rules as the server (callTracker.normalizePhoneNumber) — used for the visibility check. */
export const normalizeDialNumber = (raw: any): string => {
  let s = String(raw ?? '').trim()
  if (!s) return ''
  if (/^\*\d{2,3}$/.test(s)) return s
  s = s.replace(/\(0\)/g, '').replace(/^\+/, '00').replace(/[\s\-/().]/g, '')
  return /^\d{3,20}$/.test(s) ? s : ''
}

export const useDialCapability = () => useState<DialCapability>('dialCapability', () => ({ loaded: false, enabled: false, canDial: false, extension: null }))

let loadingPromise: Promise<void> | null = null

export const useClickToDial = () => {
  const capability = useDialCapability()
  const config = useRuntimeConfig()
  const { t } = useTranslation()

  const load = async (force = false) => {
    if (import.meta.server) return
    if (config.public.clickToDialEnabled !== true) { capability.value = { loaded: true, enabled: false, canDial: false, extension: null }; return }
    if (capability.value.loaded && !force) return
    if (loadingPromise && !force) return loadingPromise
    loadingPromise = (async () => {
      try {
        const res: any = await $fetch('/api/telephony/me', { headers: useRequestHeaders(['cookie']) })
        capability.value = { loaded: true, enabled: res?.enabled === true, canDial: res?.canDial === true, extension: res?.extension || null }
      } catch {
        capability.value = { loaded: true, enabled: false, canDial: false, extension: null }
      } finally {
        loadingPromise = null
      }
    })()
    return loadingPromise
  }

  const canDial = computed(() => capability.value.canDial === true)
  const dialing = ref(false)

  /** PBX extension directory (cached per session in state; refreshed on demand). */
  const directory = useState<{ loaded: boolean; records: DirectoryExtension[] }>('dialDirectory', () => ({ loaded: false, records: [] }))
  const loadDirectory = async (force = false) => {
    if (directory.value.loaded && !force) return directory.value.records
    try {
      const res: any = await $fetch('/api/telephony/extensions', { headers: useRequestHeaders(['cookie']) })
      directory.value = { loaded: true, records: Array.isArray(res?.records) ? res.records : [] }
    } catch {
      directory.value = { loaded: true, records: [] }
    }
    return directory.value.records
  }

  const dial = async (target: DialTarget) => {
    const number = normalizeDialNumber(target?.number)
    if (!number) {
      toast({ message: t.value?.dial_invalid_number || 'Ungültige Telefonnummer', type: 'is-warning', duration: 2500 })
      return null
    }
    if (dialing.value) return null
    dialing.value = true
    try {
      const res: any = await $fetch('/api/telephony/dial', {
        method: 'POST',
        headers: useRequestHeaders(['cookie']),
        body: {
          number,
          targetUserId: target?.userId || null,
          targetPartnerId: target?.partnerId || null,
          targetLabel: target?.label || '',
          ...(target?.extension ? { extension: String(target.extension) } : {})
        }
      })
      if (Number(res?.status) === 200) {
        const who = target?.label ? `${target.label} (${number})` : number
        const ext = res?.extension ? ` [${t.value?.dial_extension_short || 'Nst.'} ${res.extension}]` : ''
        toast({ message: `${t.value?.dial_ringing || 'Ihr Telefon klingelt – Anruf an'} ${who}${ext}`, type: 'is-success', duration: 4000 })
        return res
      }
      toast({ message: res?.message || t.value?.dial_failed || 'Anruf fehlgeschlagen', type: 'is-danger', duration: 4000 })
      return res
    } catch (err: any) {
      const status = Number(err?.status || err?.statusCode || 0)
      if (status === 403) capability.value = { ...capability.value, canDial: false }
      toast({ message: err?.data?.statusMessage || err?.data?.message || t.value?.dial_failed || 'Anruf fehlgeschlagen', type: 'is-danger', duration: 4000 })
      return null
    } finally {
      dialing.value = false
    }
  }

  return { capability, canDial, dialing, load, dial, normalizeDialNumber, directory, loadDirectory }
}
