import fetchHelper from './fetchHelper'
import type { EncryptedBlob } from './passwordCipher'

// Shape stored in ad_user.WebAuthnCredentials (Text/CLOB column).
// Read returns the canonical PascalCase column name; writes use lowercase-first
// (`webAuthnCredentials`) per iDempiere REST casing rules.
export interface WebAuthnKeyEntry {
  credentialId: string         // base64url credential id
  publicKey: string            // base64 of Uint8Array (Buffer.toString('base64'))
  counter: number
  transports?: string[]
  nickname: string
  createdAt: number            // ms epoch
  deviceType?: string          // 'singleDevice' | 'multiDevice'
  backedUp?: boolean
}

export interface WebAuthnCredentialsPayload {
  keys: WebAuthnKeyEntry[]
  password: EncryptedBlob | null
}

const EMPTY: WebAuthnCredentialsPayload = { keys: [], password: null }

function getServiceToken(): string {
  const config = useRuntimeConfig()
  const token: string | undefined = (config.api as any)?.idempieretoken
  if (!token) {
    throw new Error('IDEMPIERETOKEN env var is not set — cannot read/write ad_user without a user session')
  }
  return token
}

function parseColumn(rec: any): WebAuthnCredentialsPayload {
  if (!rec) return { ...EMPTY }
  const raw = rec.WebAuthnCredentials ?? rec.webAuthnCredentials ?? null
  if (!raw) return { ...EMPTY }
  try {
    const obj = typeof raw === 'string' ? JSON.parse(raw) : raw
    return {
      keys: Array.isArray(obj?.keys) ? obj.keys : [],
      password: obj?.password ?? null,
    }
  } catch {
    return { ...EMPTY }
  }
}

export async function readCredentials(event: any, userId: number, token?: string): Promise<WebAuthnCredentialsPayload> {
  const tk = token || getServiceToken()
  const rec: any = await fetchHelper(event, 'models/ad_user/' + userId, 'GET', tk, null)
  return parseColumn(rec)
}

export async function writeCredentials(event: any, userId: number, payload: WebAuthnCredentialsPayload, token?: string): Promise<void> {
  const tk = token || getServiceToken()
  const serialized = JSON.stringify(payload)
  await fetchHelper(event, 'models/ad_user/' + userId, 'PUT', tk, {
    webAuthnCredentials: serialized,
    tableName: 'AD_User',
  })
}

export async function fetchUserName(event: any, userId: number, token?: string): Promise<string | null> {
  const tk = token || getServiceToken()
  const rec: any = await fetchHelper(event, 'models/ad_user/' + userId, 'GET', tk, null).catch(() => null)
  if (!rec) return null
  // iDempiere ad_user has Name (display) and Value (login id). Use Name as the
  // login identifier — that's what auth/tokens accepts (see login.post.ts and
  // auto-defaults.post.ts which both query by `name eq '...'`).
  return rec.Name ?? rec.name ?? rec.Value ?? rec.value ?? null
}
