/**
 * Shared presentation helpers for security keys (YubiKey) — used by the overview page
 * (/users/security-keys), the profile / user-edit panel and the enrol + revoke modals so
 * dates, transport labels, initials and WebAuthn error texts read the same everywhere.
 */
export interface SecurityKeyRow {
  credentialId: string
  nickname: string
  createdAt?: number | null
  lastUsedAt?: number | null
  transports?: string[]
  enrolledBy?: number | null
  enrolledByName?: string | null
  userId?: number
  userName?: string
  userValue?: string
}

export const useSecurityKeyFormat = () => {
  const { t, lang } = useTranslation() as any

  const locale = computed(() => String(lang?.value || 'en-US'))

  const fmtAbsolute = (ts?: number | string | null): string => {
    if (!ts) return ''
    try {
      return new Date(ts).toLocaleString(locale.value, { dateStyle: 'medium', timeStyle: 'short' })
    } catch { return '' }
  }

  /** "today 10:21" / "yesterday" / "3 days ago" / absolute date beyond 30 days. */
  const fmtRelative = (ts?: number | string | null): string => {
    if (!ts) return ''
    const d = new Date(ts)
    if (Number.isNaN(d.getTime())) return ''
    const now = Date.now()
    const diffDays = Math.floor((now - d.getTime()) / 86_400_000)
    const time = d.toLocaleTimeString(locale.value, { hour: '2-digit', minute: '2-digit' })
    const tr: any = t.value || {}
    if (diffDays <= 0) return `${tr.today || 'today'} ${time}`
    if (diffDays === 1) return `${tr.yesterday || 'yesterday'} ${time}`
    if (diffDays < 30) {
      try {
        return new Intl.RelativeTimeFormat(locale.value, { numeric: 'auto' }).format(-diffDays, 'day')
      } catch { return `${diffDays} d` }
    }
    try { return d.toLocaleDateString(locale.value, { dateStyle: 'medium' }) } catch { return '' }
  }

  const transportMap = (): Record<string, string> => ({
    usb: 'USB',
    nfc: 'NFC',
    ble: 'Bluetooth',
    internal: (t.value as any)?.transport_internal || 'Device',
    hybrid: 'Phone',
  })
  const transportLabel = (list?: string[] | null): string => {
    const map = transportMap()
    return (list || []).map(x => map[x] || x).join(', ') || '—'
  }
  const transportItems = (list?: string[] | null) => {
    const map = transportMap()
    const icons: Record<string, string> = {
      usb: 'i-mdi-usb-port', nfc: 'i-mdi-nfc', ble: 'i-mdi-bluetooth', internal: 'i-mdi-cellphone-key', hybrid: 'i-mdi-cellphone-link',
    }
    return (list || []).map(x => ({ key: x, label: map[x] || x, icon: icons[x] || 'i-mdi-key-variant' }))
  }

  const initials = (name?: string | null): string => {
    const parts = String(name || '').trim().split(/\s+/).filter(Boolean)
    if (!parts.length) return '?'
    return (parts[0]![0]! + (parts.length > 1 ? parts[parts.length - 1]![0]! : '')).toUpperCase()
  }

  /** Map a WebAuthn / fetch failure to a human sentence. */
  const errorMessage = (err: any, fallback?: string): string => {
    const tr: any = t.value || {}
    const name = String(err?.name || '')
    if (name === 'InvalidStateError') return tr.security_key_already_enrolled || 'This key is already enrolled for this user.'
    if (name === 'NotAllowedError' || name === 'AbortError') return tr.security_key_login_cancelled_hint || 'No security key was read. Tap the key again.'
    if (name === 'NotSupportedError') return tr.security_key_not_supported || 'Your browser or device does not support security keys.'
    if (name === 'SecurityError') return tr.security_key_origin_error || 'This page is not allowed to talk to security keys (origin mismatch).'
    return err?.data?.statusMessage || err?.data?.message || err?.message || fallback || tr.security_key_error || 'Could not complete the security key operation.'
  }

  /** Was the failure just the user cancelling / nothing tapped? (→ no error toast) */
  const isCancelled = (err: any): boolean => {
    const name = String(err?.name || '')
    return name === 'AbortError' || name === 'NotAllowedError'
  }

  return { fmtAbsolute, fmtRelative, transportLabel, transportItems, initials, errorMessage, isCancelled }
}
