import { string } from 'alga-js'

// Per-order invoice generation via the iDempiere process c_invoice_generate.
// Extracted from pages/generate-invoices-from-orders.vue so the marketplace
// orders-check pages (Amazon/eBay) can create invoices for selected rows with
// the exact same semantics. The process response carries no invoice id — only
// log lines — so the DocumentNo is parsed out of the logs and the invoice is
// then resolved via the generic c_invoice filter endpoint.

export const useInvoiceGenerate = () => {
  const headers = useRequestHeaders(['cookie'])

  const extractDocumentNo = (str: any): string => {
    const s = String(str ?? '')
    // English session: "... Processed:  1000216"
    const candidate = s.split('Processed:')?.[1]?.trim() ?? ''
    if (candidate !== '') return candidate
    // Language-agnostic fallback — iDempiere translates the label per session
    // language, but the log line always ends with ": <DocumentNo>". Doc numbers
    // may be non-numeric, so take the last token after the colon.
    const m = s.match(/:\s*(\S+)\s*$/)
    return m ? m[1] : ''
  }

  const lookupInvoice = async (docNo: string, orderId: number | null = null): Promise<any> => {
    if (!docNo) return null
    const fetchOne = async (filter: string) => {
      const res: any = await $fetch(`/api/filters/c_invoice/${string.urlEncode(filter)}`, { headers })
      return res?.records?.[0] || null
    }
    try {
      // AND the order id into the filter so a DocumentNo shared with another
      // doctype can't resolve to the wrong record; the filter endpoint orders
      // c_invoice_id desc, so records[0] is the newest on the fallback path too.
      let rec = await fetchOne(
        `DocumentNo eq '${docNo}'` + (orderId ? ` and C_Order_ID eq ${orderId}` : '')
      )
      if (!rec && orderId) rec = await fetchOne(`DocumentNo eq '${docNo}'`)
      if (rec) {
        return {
          invoiceId: rec.id,
          invoiceDocNo: rec.DocumentNo,
          invoiceDate: rec.DateInvoiced,
          amount: rec.GrandTotal,
          currency: rec.C_Currency_ID?.identifier || '',
          docStatus: rec.DocStatus?.id || rec.DocStatus?.identifier || rec.DocStatus || ''
        }
      }
    } catch (e) {}
    return null
  }

  // Runs the process for ONE order. Never throws — callers can loop safely.
  // status: 'success' = doc no parsed + invoice resolved; 'warning' = process ok
  // but no doc no (nothing generated) or lookup missed; 'error' = process failed.
  const generateInvoiceForOrder = async ({ orderId, organizationId, dateInvoiced, docAction = 'CO' }: {
    orderId: number
    organizationId: number | string
    dateInvoiced: string
    docAction?: string
  }): Promise<any> => {
    try {
      const res: any = await $fetch('/api/processes/c_invoice_generate', {
        method: 'POST',
        headers,
        body: {
          dateInvoiced,
          organizationId,
          orderId,
          docAction,
          consolidateDocument: false
        }
      })

      if (Number(res?.status) === 200 && Number(res?.logs?.length || 0) >= 1) {
        const docNos: string[] = []
        for (const log of res.logs || []) {
          const extracted = extractDocumentNo(log?.msg ?? log)
          if (extracted && !docNos.includes(extracted)) docNos.push(extracted)
        }
        if (docNos.length) {
          const invoice = await lookupInvoice(docNos[0], orderId)
          return {
            status: invoice ? 'success' : 'warning',
            docNos,
            invoice,
            summary: res.summary || '',
            message: res.summary || (invoice ? 'Rechnung erstellt' : 'Rechnung erstellt (Details nicht auflösbar)')
          }
        }
        return {
          status: 'warning',
          docNos: [],
          invoice: null,
          summary: res.summary || '',
          message: res.summary || 'Keine Rechnung erzeugt'
        }
      }

      return {
        status: 'error',
        docNos: [],
        invoice: null,
        summary: res?.summary || '',
        message: res?.message || res?.summary || 'Rechnungserstellung fehlgeschlagen'
      }
    } catch (err: any) {
      return {
        status: 'error',
        docNos: [],
        invoice: null,
        summary: '',
        message: err?.data?.message || err?.message || 'Rechnungserstellung fehlgeschlagen'
      }
    }
  }

  return { extractDocumentNo, lookupInvoice, generateInvoiceForOrder }
}
