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

// GET /api/bi/bank-cash-report?year=2026
// Raw material for the cash-basis GuV / EÜR BI reports: every bank statement
// line (c_bankstatementline, all bank accounts, Drafted + Completed statements)
// whose StatementLineDate falls into the requested year, plus the own bank
// accounts (needed client-side to flag transfers between own accounts).
// No account assignment / posting relevance — the sign of StmtAmt decides
// income (+) vs expense (−); all grouping happens in useBankCashReport().
const PAGE = 500
const MAX_LINES = 20000

const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const query = getQuery(event)
  const now = new Date()
  let year = Number(query.year) || now.getFullYear()
  if (!Number.isInteger(year) || year < 2000 || year > now.getFullYear() + 1) year = now.getFullYear()

  // Own bank accounts (Volksbank, PayPal, …) — small list, one request.
  const accRes: any = await event.context.fetch(
    'models/c_bankaccount?$select=C_BankAccount_ID,Name,AccountNo,IBAN,IsActive,C_Bank_ID' +
    `&$expand=${string.urlEncode('C_Bank_ID($select=Name)')}&$orderby=C_BankAccount_ID&$top=50`,
    'GET', token, null
  )
  const accounts = (accRes?.records || []).map((a: any) => ({
    id: a.id,
    name: a.Name || a.identifier || `#${a.id}`,
    accountNo: a.AccountNo || '',
    iban: a.IBAN || '',
    bankName: a.C_Bank_ID?.Name || a.C_Bank_ID?.identifier || '',
    isActive: a.IsActive !== false
  }))

  const filter = string.urlEncode(
    `StatementLineDate ge '${year}-01-01 00:00:00' and StatementLineDate le '${year}-12-31 23:59:59'`
  )
  const select = '$select=C_BankStatementLine_ID,StatementLineDate,ValutaDate,StmtAmt,TrxAmt,ChargeAmt,' +
    'EftPayee,EftPayeeAccount,EftMemo,Description,ReferenceNo,C_BankStatement_ID,C_Payment_ID,C_Charge_ID,C_BPartner_ID'
  const expand = '$expand=' + string.urlEncode(
    'C_BankStatement_ID($select=DocumentNo,DocStatus,C_BankAccount_ID),' +
    'C_Payment_ID($select=DocumentNo),C_Charge_ID($select=Name),C_BPartner_ID($select=Name)'
  )
  const orderby = string.urlEncode('StatementLineDate,C_BankStatementLine_ID')

  const records: any[] = []
  let skip = 0
  let truncated = false
  while (true) {
    const res: any = await event.context.fetch(
      `models/c_bankstatementline?$filter=${filter}&${select}&${expand}&$orderby=${orderby}&$top=${PAGE}&$skip=${skip}`,
      'GET', token, null
    )
    const page = res?.records || []
    records.push(...page)
    if (page.length < PAGE) break
    skip += PAGE
    if (records.length >= MAX_LINES) { truncated = true; break }
  }

  const lines = records
    .filter((r: any) => {
      const st = r.C_BankStatement_ID?.DocStatus?.id || r.C_BankStatement_ID?.DocStatus || ''
      return st !== 'VO' && st !== 'RE'   // voided / reversed statements never count
    })
    .map((r: any) => ({
      id: r.id,
      date: String(r.StatementLineDate || '').slice(0, 10),
      valutaDate: r.ValutaDate ? String(r.ValutaDate).slice(0, 10) : null,
      amount: Number(r.StmtAmt ?? 0),
      trxAmt: Number(r.TrxAmt ?? 0),
      chargeAmt: Number(r.ChargeAmt ?? 0),
      accountId: r.C_BankStatement_ID?.C_BankAccount_ID?.id || null,
      statementId: r.C_BankStatement_ID?.id || null,
      statementNo: r.C_BankStatement_ID?.DocumentNo || r.C_BankStatement_ID?.identifier || '',
      statementStatus: r.C_BankStatement_ID?.DocStatus?.id || r.C_BankStatement_ID?.DocStatus || '',
      counterpart: r.EftPayee || '',
      counterpartAccount: r.EftPayeeAccount || '',
      memo: r.EftMemo || r.Description || '',
      reference: r.ReferenceNo || '',
      matched: r.C_Payment_ID?.id ? 'payment' : (r.C_Charge_ID?.id ? 'charge' : null),
      paymentNo: r.C_Payment_ID?.DocumentNo || r.C_Payment_ID?.identifier || '',
      chargeName: r.C_Charge_ID?.Name || r.C_Charge_ID?.identifier || '',
      partnerName: r.C_BPartner_ID?.Name || r.C_BPartner_ID?.identifier || ''
    }))

  return { status: 200, year, accounts, lines, total: lines.length, truncated, generatedAt: new Date().toISOString() }
}

export default defineEventHandler(async (event) => {
  let data: any = {}
  try {
    data = await handleFunc(event)
  } catch (err: any) {
    try {
      const authToken = await refreshTokenHelper(event)
      data = await handleFunc(event, authToken)
    } catch (error: any) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
    }
  }
  return data
})
