/**
 * Customs (CN23) tax note on C_Order.Description.
 *
 * The eBay import (laravel-middleware IdempiereOrderRepository::postOrder) writes,
 * when the marketplace collected the VAT itself (IOSS/OSS), exactly this sentence
 * into the order Description:
 *
 *   Tax of {amount} {currency} has been paid via {paidVia} ({scheme}) with Code: {code}
 *
 * The only consumer is the DHL customs declaration: commission/parcels/dhl/{index,multi}
 * send the first 80 chars of C_Order.Description as CN23 `exportDescription`. This
 * composable lets staff set the same note manually (order popup + order edit) with the
 * identical format, so imported and manual orders look the same on the customs form.
 *
 * The note is always the FIRST line of the Description; any other text is kept after it.
 */
export interface CustomsTaxNote {
  paidVia: string
  scheme: string
  amount: string
  currency: string
  code: string
}

export const CUSTOMS_TAX_SCHEMES = ['IOSS', 'OSS', 'VAT', 'other'] as const

/** DHL CN23 exportDescription cap (dhl/index.post.ts + dhl/multi.post.ts). */
export const CUSTOMS_EXPORT_DESCRIPTION_MAX = 80

// Exact eBay-import format; `m` so the note may be one line of a longer Description.
// The code may contain spaces (real data: "GB 365 6085 76"); iDempiere appends " | ** Voided"
// on void, which is excluded from the code and kept out of the match.
const NOTE_RE = /^Tax of ([0-9]+(?:[.,][0-9]+)?) ([A-Za-z]{3}) has been paid via (.+?) \((.+?)\) with Code: (.+?)(?=[ \t]*\|[ \t]*\*\*|[ \t]*$)/m

export const useCustomsTaxNote = () => {
  const { isDhlShipper } = useDhlShipper()

  /**
   * Carrier gate for the UI: only shippers whose customs path reads the note.
   * Today that is DHL-Paket only — extend here for DPD once its customs
   * request carries the order Description.
   */
  const isCustomsTaxNoteShipper = (shipperId: any): boolean => isDhlShipper(shipperId)

  const formatAmount = (v: string | number | null | undefined): string => {
    const n = Number(String(v ?? '').trim().replace(',', '.'))
    return Number.isFinite(n) && String(v ?? '').trim() !== '' ? n.toFixed(2) : ''
  }

  const isComplete = (p?: CustomsTaxNote | null): boolean =>
    !!p
    && formatAmount(p.amount) !== ''
    && /^[A-Za-z]{3}$/.test(String(p.currency || '').trim())
    && String(p.paidVia || '').trim() !== ''
    && String(p.scheme || '').trim() !== ''
    && String(p.code || '').trim() !== ''

  const build = (p?: CustomsTaxNote | null): string => {
    if (!isComplete(p)) return ''
    const n = p as CustomsTaxNote
    return `Tax of ${formatAmount(n.amount)} ${String(n.currency).trim().toUpperCase()} has been paid via ${String(n.paidVia).trim()} (${String(n.scheme).trim()}) with Code: ${String(n.code).trim()}`
  }

  const parse = (text?: string | null): CustomsTaxNote | null => {
    const m = NOTE_RE.exec(String(text || ''))
    if (!m) return null
    return {
      amount: formatAmount(m[1]) || m[1],
      currency: m[2].toUpperCase(),
      paidVia: m[3].trim(),
      scheme: m[4].trim(),
      code: m[5].trim()
    }
  }

  /** Remove the note line (and the blank it leaves) from a Description. */
  const strip = (text?: string | null): string =>
    String(text || '')
      .replace(NOTE_RE, '')
      .split(/\r?\n/)
      .filter((line, idx, arr) => !(line.trim() === '' && (idx === 0 || idx === arr.length - 1)))
      .join('\n')
      .trim()

  /**
   * Returns the Description with the note as its first line (replacing an
   * existing one), or without any note when `p` is null / incomplete. Idempotent.
   */
  const apply = (description: string | null | undefined, p: CustomsTaxNote | null): string => {
    const rest = strip(description)
    const note = build(p)
    if (!note) return rest
    return rest ? `${note}\n${rest}` : note
  }

  return {
    build,
    parse,
    apply,
    strip,
    isComplete,
    formatAmount,
    isCustomsTaxNoteShipper,
    schemes: CUSTOMS_TAX_SCHEMES,
    maxLength: CUSTOMS_EXPORT_DESCRIPTION_MAX
  }
}
