// Resolves the physical label size (mm) for a CUPS queue.
//
// Order of truth:
//   1. App printer registry (iDempiere `CUST_Printer`, columns LabelWidthMm /
//      LabelHeightMm, maintained at Settings → Printers) — matched by CupsName.
//   2. The CUPS queue's own default PageSize (see cupsMedia.ts).
//   3. null → caller keeps its legacy page format.
//
// The registry columns may not exist yet: the read is done WITHOUT `$select`
// (a missing column would 400) and any error degrades to an empty map.

import fetchHelper from './fetchHelper'
import getTokenHelper from './getTokenHelper'
import { getQueueMediaMm, type MediaMm } from './cupsMedia'

export interface ResolvedMedia extends MediaMm {
  source: 'registry' | 'cups'
  /** Label product identification (CUST_Printer.LabelType), registry only. */
  labelType?: string
}

export interface RegistryLabelInfo extends MediaMm { labelType: string }

const CACHE_TTL = 5 * 60 * 1000
const registryCache = new Map<string, { value: Map<string, RegistryLabelInfo>; ts: number }>()

const num = (v: any): number => {
  const n = Number(v)
  return Number.isFinite(n) && n > 0 ? n : 0
}

/** Registry label sizes keyed by CUPS queue name for the current org (+ org 0). */
export const getRegistryLabelSizes = async (event: any): Promise<Map<string, RegistryLabelInfo>> => {
  const organizationId = getCookie(event, 'logship_organization_id') || '0'
  const hit = registryCache.get(organizationId)
  if (hit && Date.now() - hit.ts < CACHE_TTL) return hit.value

  const map = new Map<string, RegistryLabelInfo>()
  try {
    const token = await getTokenHelper(event)
    const filter = `(AD_Org_ID eq ${organizationId} or AD_Org_ID eq 0) and IsActive eq true`
    const res: any = await fetchHelper(event, `models/cust_printer?$filter=${encodeURIComponent(filter)}`, 'GET', token, null)
    const records: any[] = Array.isArray(res?.records) ? res.records : []
    for (const r of records) {
      const cups = String(r?.CupsName ?? r?.cupsName ?? r?.cupsname ?? '').trim()
      if (!cups) continue
      const w = num(r?.LabelWidthMm ?? r?.labelWidthMm ?? r?.labelwidthmm)
      const h = num(r?.LabelHeightMm ?? r?.labelHeightMm ?? r?.labelheightmm)
      if (!w || !h) continue
      const labelType = String(r?.LabelType ?? r?.labelType ?? r?.labeltype ?? '').trim()
      const orgId = Number(r?.AD_Org_ID?.id ?? r?.AD_Org_ID ?? 0)
      // Org-specific row wins over the shared (org 0) row for the same queue.
      const existing = map.get(cups) as any
      if (existing && existing._orgId !== 0 && orgId === 0) continue
      map.set(cups, Object.assign({ w, h, labelType }, { _orgId: orgId }) as any)
    }
  } catch (err: any) {
    console.warn(`[labelMedia] registry read failed: ${err?.message || err}`)
  }
  registryCache.set(organizationId, { value: map, ts: Date.now() })
  return map
}

export const clearRegistryLabelCache = () => { registryCache.clear() }

/** Registry size → CUPS default → null. */
export const resolveLabelMedia = async (event: any, queue: string): Promise<ResolvedMedia | null> => {
  const q = String(queue || '').trim()
  if (!q) return null
  const registry = await getRegistryLabelSizes(event)
  const reg = registry.get(q)
  if (reg) return { w: reg.w, h: reg.h, source: 'registry', labelType: reg.labelType || undefined }
  const cups = await getQueueMediaMm(q)
  if (cups) return { w: cups.w, h: cups.h, source: 'cups' }
  return null
}
