import refreshTokenHelper from "../../utils/refreshTokenHelper"
import forceLogoutHelper from "../../utils/forceLogoutHelper"
import errorHandlingHelper from "../../utils/errorHandlingHelper"
import toIdempiereDate from "../../utils/idempiereDate"
import {
  CSV_EXPORT_FLAG_COL,
  CSV_EXPORT_DATE_COL,
  isCsvExportColumnError,
  markCsvExportColumnsMissing,
  markCsvExportColumnsPresent
} from "../../utils/lexofficeCsvExportMark"

// Marks (or un-marks) orders as "exported to lexoffice via settlement CSV".
//   POST body: { orderIds: number[], exported: boolean }
//   → { status, updatedCount, updatedIds, errors? }
// Called by the settlement pages right after a positions-containing CSV download
// (exported=true, all matched orders of the exported periods) and by their
// "CSV-Export-Markierung zurücksetzen" actions (exported=false). Writes are
// independent per order (fail-soft per id, bounded concurrency) — a single bad
// order never blocks the rest. See server/utils/lexofficeCsvExportMark.ts for
// the column contract.

const CONCURRENCY = 5

const handleFunc = async (event: any, authToken: any = null) => {
  const token = authToken ?? await getTokenHelper(event)
  const body = await readBody(event)
  const orderIds: number[] = [...new Set((body?.orderIds || []).map((id: any) => Number(id)).filter((id: number) => Number.isFinite(id) && id > 0))]
  const exported = body?.exported !== false

  if (!orderIds.length) {
    return { status: 400, message: 'No order IDs provided' }
  }

  const payload: Record<string, any> = {
    [CSV_EXPORT_FLAG_COL]: exported,
    [CSV_EXPORT_DATE_COL]: exported ? toIdempiereDate(new Date()) : null
  }

  const errors: string[] = []
  const updatedIds: number[] = []
  let columnMissing = false
  let authError: any = null

  const queue = [...orderIds]
  const worker = async () => {
    while (queue.length) {
      if (columnMissing || authError) return
      const orderId = queue.shift() as number
      try {
        await event.context.fetch(`models/c_order/${orderId}`, 'PUT', token, payload)
        updatedIds.push(orderId)
      } catch (err: any) {
        if (isCsvExportColumnError(err)) { columnMissing = true; return }
        const status = Number(err?.statusCode || err?.status || err?.data?.status || 0)
        if (status === 401) { authError = err; return }
        errors.push(`Order ${orderId}: ${err?.data?.detail || err?.data?.message || err?.message || 'Unknown error'}`)
      }
    }
  }
  await Promise.all(Array.from({ length: Math.min(CONCURRENCY, orderIds.length) }, worker))

  // Let the outer handler run the token-refresh retry.
  if (authError) throw authError

  if (columnMissing) {
    markCsvExportColumnsMissing()
    return {
      status: 400,
      message: `Die Spalten ${CSV_EXPORT_FLAG_COL} / ${CSV_EXPORT_DATE_COL} fehlen auf C_Order — die CSV-Export-Markierung kann erst nach dem Anlegen der Spalten in iDempiere gespeichert werden.`,
      updatedCount: updatedIds.length,
      updatedIds,
      columnMissing: true
    }
  }
  markCsvExportColumnsPresent()

  if (updatedIds.length > 0) {
    return {
      status: 200,
      message: exported
        ? `${updatedIds.length} Auftrag/Aufträge als CSV-exportiert markiert`
        : `CSV-Export-Markierung für ${updatedIds.length} Auftrag/Aufträge zurückgesetzt`,
      updatedCount: updatedIds.length,
      updatedIds,
      errors: errors.length ? errors : undefined
    }
  }
  return {
    status: 400,
    message: exported ? 'Keine Aufträge markiert' : 'Keine Markierung zurückgesetzt',
    updatedCount: 0,
    updatedIds,
    errors
  }
}

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
})
