import { string } from 'alga-js'
import refreshTokenHelper from "../../utils/refreshTokenHelper"
import forceLogoutHelper from "../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../utils/errorHandlingHelper"

/**
 * Fulfillment customer invoices endpoint
 * Uses service token to fetch invoices for the business partner linked to the customer's org
 */
const handleFunc = async (event: any, authToken: any = null) => {
  let data: any = {}
  const config = useRuntimeConfig()
  const serviceToken = config.api.idempieretoken
  const organizationId = getCookie(event, 'logship_organization_id')

  let bpartnerId: number | null = null
  let isAllowFeeReportDownload = false

  if (!organizationId || !serviceToken) {
    return { records: [], isAllowFeeReportDownload: false }
  }

  try {
    // Get the org's business partner ID using the service token
    const orgFilter = `AD_Org_ID eq ${organizationId}`
    const orgUrl = `${config.api.url}/models/ad_org?$filter=${string.urlEncode(orgFilter)}&$select=C_BPartner_ID`

    const orgRes: any = await $fetch(orgUrl, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        Authorization: 'Bearer ' + serviceToken
      }
    })

    bpartnerId = orgRes?.records?.[0]?.C_BPartner_ID?.id

    if (!bpartnerId) {
      return { records: [], isAllowFeeReportDownload: false }
    }

    // Check if fee report download is allowed for this business partner
    const bpartnerRes: any = await $fetch(`${config.api.url}/models/c_bpartner/${bpartnerId}?$select=isAllowFeeReportDownload`, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        Authorization: 'Bearer ' + serviceToken
      }
    })
    isAllowFeeReportDownload = bpartnerRes?.isAllowFeeReportDownload === 'Y' || bpartnerRes?.isAllowFeeReportDownload === true

    // Fetch invoices for this business partner using service token
    // Only show invoices with DocStatus CO (Completed) or CL (Closed)
    const bpartnerFilter = `C_BPartner_ID eq ${bpartnerId} and (DocStatus eq 'CO' or DocStatus eq 'CL')`
    const invoiceUrl = `${config.api.url}/models/C_Invoice?$filter=${string.urlEncode(bpartnerFilter)}&$select=C_Invoice_ID,C_Invoice_UU,IsActive,DocumentNo,Description,IsApproved,IsPaid,IsPrinted,IsTransferred,DateOrdered,DateInvoiced,DateAcct,TotalLines,GrandTotal,ChargeAmt,Processed,IsSOTrx,IsDiscountPrinted,IsTaxIncluded,SendEMail,IsSelfService,ProcessedOn,IsPayScheduleValid,IsInDispute,IsFixedAssetInvoice,IsOverrideCurrencyRate,DocStatus,C_DocType_ID,C_DocTypeTarget_ID,DocBaseType,SalesRep_ID,AD_User_ID,C_PaymentTerm_ID,C_Currency_ID,PaymentRule,M_PriceList_ID,C_BPartner_ID,C_BPartner_Location_ID,AD_Org_ID,AD_Client_ID,C_Order_ID,isUploadToPayJoe,UploadDatePayJoe,isUploadToLexoffice,UploadDateLexoffice&$expand=C_Order_ID($select=Report_Strapi_Reference)&$orderby=C_Invoice_ID desc`

    const res: any = await $fetch(invoiceUrl, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
        Authorization: 'Bearer ' + serviceToken
      }
    })

    // Fetch allocation lines to get total paid amount for each invoice
    if (res?.records?.length > 0) {
      const invoiceIds = res.records.map((inv: any) => inv.id)

      try {
        const allocUrl = `${config.api.url}/models/c_allocationline?$filter=${string.urlEncode(`C_Invoice_ID in (${invoiceIds.join(',')})`)}&$select=C_Invoice_ID,Amount,C_Payment_ID&$expand=C_Payment_ID($select=DocStatus)`
        const allocRes: any = await $fetch(allocUrl, {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            Accept: 'application/json',
            Authorization: 'Bearer ' + serviceToken
          }
        })

        if (allocRes?.records?.length > 0) {
          // Sum up allocations per invoice
          // Keep raw signed amounts so reversals (negative) cancel out originals (positive)
          const allocationSums: Record<number, number> = {}
          for (const alloc of allocRes.records) {
            const invoiceId = alloc.C_Invoice_ID?.id
            const paymentDocStatus = alloc.C_Payment_ID?.DocStatus?.id || alloc.C_Payment_ID?.DocStatus || ''
            // Only count allocations where the related payment is completed (CO)
            if (invoiceId && paymentDocStatus === 'CO') {
              allocationSums[invoiceId] = (allocationSums[invoiceId] || 0) + (alloc.Amount || 0)
            }
          }

          // Add total paid amount to each invoice record (absolute value of net sum)
          for (const invoice of res.records) {
            invoice.TotalPaidAmt = Math.abs(allocationSums[invoice.id] || 0)
          }
        }
      } catch (err) {
        console.warn('Could not fetch allocation lines for fulfillment invoices:', err)
      }
    }

    if (res) {
      data = {
        ...res,
        isAllowFeeReportDownload
      }
    }
  } catch (err) {
    console.warn('Could not fetch fulfillment invoices:', err)
    return { records: [], isAllowFeeReportDownload: false }
  }

  return data
}

export default defineEventHandler(async (event) => {
  let data: any = {}

  try {
    data = await handleFunc(event)
  } catch (err: any) {
    try {
      let authToken: any = await refreshTokenHelper(event)
      data = await handleFunc(event, authToken)
    } catch (error) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      forceLogoutHelper(event, data)
    }
  }

  return data
})
