import refreshTokenHelper from "../../../utils/refreshTokenHelper"
import getTokenHelper from "../../../utils/getTokenHelper"
import forceLogoutHelper from "../../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../../utils/errorHandlingHelper"
import { archiveUpload, isValidToken, loadUpload, planAccount, writeDay } from "../../../utils/banking/bankFileImport"

// POST /api/accounting/bank-file-import/import
// Body: { token, iban, days: ['2026-06-23', …] }  — the client sends the days in
// small chunks (sequentially) so one request never outlives the proxy timeout.
// The plan is RECOMPUTED against live iDempiere data right before writing, so a
// booking that arrived in the meantime (EBICS fetch, second browser tab) is
// still recognised as a duplicate. Statements are created Drafted.
const MAX_DAYS_PER_REQUEST = 10

const handleFunc = async (event: any, account: any, days: string[], sourceLabel: string, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const plan = await planAccount(event, token, account, days)
  if (!plan.bankAccount) {
    return { status: 409, message: `Kein aktives iDempiere-Bankkonto mit IBAN ${account.iban} gefunden` }
  }
  const results = []
  // Oldest first — keeps DocumentNo order aligned with the balance chain.
  for (const day of plan.days) {
    results.push(await writeDay(event, token, plan, day, sourceLabel))
  }
  return { status: 200, bankAccount: plan.bankAccount, results }
}

export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  const uploadToken = String(body?.token || '')
  if (!isValidToken(uploadToken)) return { status: 400, message: 'Ungültiges Upload-Token' }

  const parsed = await loadUpload(uploadToken)
  if (!parsed) return { status: 404, message: 'Upload nicht mehr vorhanden — bitte die Datei erneut hochladen' }

  const iban = String(body?.iban || '').replace(/\s+/g, '').toUpperCase()
  const account = parsed.accounts.find((acc: any) => acc.iban === iban) || (parsed.accounts.length === 1 && !iban ? parsed.accounts[0] : null)
  if (!account) return { status: 404, message: 'Konto nicht im Upload enthalten' }

  const days: string[] = Array.from(new Set(
    (Array.isArray(body?.days) ? body.days : []).map((d: any) => String(d)).filter((d: string) => /^\d{4}-\d{2}-\d{2}$/.test(d))
  )).sort() as string[]
  if (!days.length) return { status: 400, message: 'Keine Tage ausgewählt' }
  if (days.length > MAX_DAYS_PER_REQUEST) return { status: 400, message: `Maximal ${MAX_DAYS_PER_REQUEST} Tage pro Anfrage` }

  const sourceLabel = parsed.files.length === 1 ? parsed.files[0] : `${parsed.files[0]} +${parsed.files.length - 1}`

  let data: any = {}
  try {
    data = await handleFunc(event, account, days, sourceLabel)
  } catch (err: any) {
    try {
      // Re-planning after the refresh is safe: days whose header already exists
      // come back as `resume`, already written lines as duplicates.
      let authToken: any = await refreshTokenHelper(event)
      data = await handleFunc(event, account, days, sourceLabel, authToken)
    } catch (error: any) {
      data = errorHandlingHelper(err?.data ?? err, error?.data ?? error)
      forceLogoutHelper(event, data)
    }
  }

  if (Number(data?.status) === 200 && (data.results || []).some((r: any) => r.linesCreated > 0)) {
    await archiveUpload(uploadToken, account.iban)
  }
  return data
})
