// Per-PERIOD lexoffice CSV export state for the settlement pages (Amazon
// settlement periods / eBay payouts) — the client of
// server/api/accounting/settlement-exports (data/settlement-exports.db).
//
// The C_Order marker (isLexofficeCsvExported) only covers matched order rows.
// Fees, Ads invoices, adjustments, unmatched orders and the payout line have no
// order to carry a marker, yet they MUST go to the lexoffice clearing account
// for the period to reconcile. This log records per period whether its
// positions (complete or filtered) and its payout row already went out, so
//   - the period list shows a clearance badge (exportiert / teilweise / offen),
//   - every grid row gets a CSV status (order marker where one exists, period
//     state otherwise) and the "noch nicht als CSV exportiert" filter is honest,
//   - the export warns before a period is sent to lexoffice twice.
import type { LexofficeExportVariant } from '~/composables/useLexofficeSettlementExport'

export type SettlementMarketplace = 'amazon' | 'ebay'

export interface PeriodExportRecord {
  periodId: string
  periodLabel: string
  payoutDate: string
  amount: number | null
  currency: string
  positionsExportedAt: string | null
  positionsComplete: boolean
  positionsRowCount: number
  payoutExportedAt: string | null
  balanced: boolean | null
  lastVariant: string | null
  lastFile: string | null
  lastUser: string | null
  updatedAt: string
}

export type PeriodExportState = 'none' | 'partial' | 'complete'

export interface PeriodExportBadge {
  state: PeriodExportState
  label: string
  color: 'success' | 'warning' | 'neutral'
  title: string
}

// One period as handed to record(): the page maps its own payload into this.
export interface PeriodExportEntry {
  periodId: string
  periodLabel?: string
  payoutDate?: string
  amount?: number | null
  currency?: string
  positions: boolean
  complete: boolean
  rowCount?: number
  payout: boolean
  net?: number | null
}

const fmtDate = (s?: string | null) => {
  if (!s) return ''
  const d = new Date(s)
  return isNaN(d.getTime()) ? String(s) : d.toLocaleDateString('de-DE')
}

export const useSettlementExportLog = (marketplace: SettlementMarketplace, orderSourceId: Ref<string | number>) => {
  const periods = ref<Record<string, PeriodExportRecord>>({})
  const available = ref(true)
  const loading = ref(false)
  const busy = ref(false)
  // Bumps on every change so pages can re-decorate their rows in a watch.
  const version = ref(0)

  const headers = () => useRequestHeaders(['cookie'])
  const sourceId = () => Number(orderSourceId.value || 0)

  const load = async () => {
    periods.value = {}
    version.value++
    if (!sourceId()) return
    loading.value = true
    try {
      const res: any = await $fetch('/api/accounting/settlement-exports', {
        headers: headers(),
        query: { marketplace, orderSourceId: sourceId() }
      })
      if (Number(res?.status) === 200) {
        available.value = res.available !== false
        periods.value = res.periods || {}
      }
    } catch (e) {
      // Fail-soft: without the log the pages still work, just without badges.
      available.value = false
    } finally {
      loading.value = false
      version.value++
    }
  }

  const merge = (updated: Record<string, PeriodExportRecord> | undefined, removed: string[] = []) => {
    const next = { ...periods.value }
    for (const id of removed) delete next[id]
    for (const [id, rec] of Object.entries(updated || {})) next[id] = rec
    periods.value = next
    version.value++
  }

  // Records one produced CSV file. Returns the server message on failure, '' on success.
  const record = async (variant: LexofficeExportVariant, entries: PeriodExportEntry[], meta: { fileName?: string; rowCount?: number } = {}): Promise<string> => {
    if (!sourceId() || !entries.length) return ''
    busy.value = true
    try {
      const res: any = await $fetch('/api/accounting/settlement-exports', {
        method: 'POST',
        headers: headers(),
        body: { marketplace, orderSourceId: sourceId(), variant, fileName: meta.fileName, rowCount: meta.rowCount, periods: entries }
      })
      if (Number(res?.status) !== 200) {
        if (Number(res?.status) === 503) available.value = false
        return res?.message || 'Export-Protokoll konnte nicht gespeichert werden'
      }
      merge(res.periods)
      return ''
    } catch (e: any) {
      return e?.data?.message || e?.message || 'Export-Protokoll konnte nicht gespeichert werden'
    } finally {
      busy.value = false
    }
  }

  const reset = async (periodIds: string[], scope: 'all' | 'positions' | 'payout' = 'all'): Promise<string> => {
    const ids = [...new Set(periodIds.filter(Boolean))]
    if (!sourceId() || !ids.length) return ''
    busy.value = true
    try {
      const res: any = await $fetch('/api/accounting/settlement-exports/reset', {
        method: 'POST',
        headers: headers(),
        body: { marketplace, orderSourceId: sourceId(), periodIds: ids, scope }
      })
      if (Number(res?.status) !== 200) return res?.message || 'Zurücksetzen fehlgeschlagen'
      merge(res.periods, scope === 'all' ? ids : [])
      return ''
    } catch (e: any) {
      return e?.data?.message || e?.message || 'Zurücksetzen fehlgeschlagen'
    } finally {
      busy.value = false
    }
  }

  const get = (periodId: string | null | undefined): PeriodExportRecord | null => (periodId && periods.value[periodId]) || null

  // Clearance state of a period. `needsPayout` = the period has a payout line
  // to export at all (false for Failed / amount-0 periods).
  const stateOf = (periodId: string, needsPayout = true): PeriodExportState => {
    const r = get(periodId)
    if (!r) return 'none'
    const positionsDone = !!r.positionsExportedAt && r.positionsComplete
    const payoutDone = !needsPayout || !!r.payoutExportedAt
    if (positionsDone && payoutDone) return 'complete'
    if (r.positionsExportedAt || r.payoutExportedAt) return 'partial'
    return 'none'
  }

  const badgeOf = (periodId: string, needsPayout = true, exportable = true): PeriodExportBadge | null => {
    const r = get(periodId)
    const state = stateOf(periodId, needsPayout)
    if (state === 'none') {
      if (!exportable) return null
      return { state, label: 'offen', color: 'neutral', title: 'Noch nicht als Lexoffice-CSV exportiert' }
    }
    const parts: string[] = []
    if (r?.positionsExportedAt) parts.push(`Positionen ${r.positionsComplete ? 'vollständig' : 'gefiltert (unvollständig)'} am ${fmtDate(r.positionsExportedAt)}${r.positionsRowCount ? ` (${r.positionsRowCount} Zeilen)` : ''}`)
    else parts.push('Positionen noch nicht exportiert')
    if (needsPayout) {
      parts.push(r?.payoutExportedAt ? `Auszahlungszeile am ${fmtDate(r.payoutExportedAt)}` : 'Auszahlungszeile noch nicht exportiert')
    }
    if (r?.balanced === true) parts.push('Saldo 0,00 ✓')
    else if (r?.balanced === false) parts.push('Saldo ≠ 0,00 — bitte prüfen')
    if (r?.lastFile) parts.push(`Datei ${r.lastFile}`)
    if (r?.lastUser) parts.push(`von ${r.lastUser}`)
    const title = parts.join(' · ')
    if (state === 'complete') {
      const when = fmtDate(r?.payoutExportedAt || r?.positionsExportedAt)
      return { state, label: `exportiert${when ? ' ' + when : ''}`, color: r?.balanced === false ? 'warning' : 'success', title }
    }
    return { state, label: 'teilweise exportiert', color: 'warning', title }
  }

  // CSV status of one grid row that has NO order marker of its own.
  const rowStatus = (periodId: string | null | undefined, isPayoutRow: boolean) => {
    const r = get(periodId)
    if (!r) return { exported: false, date: '', complete: false }
    if (isPayoutRow) return { exported: !!r.payoutExportedAt, date: r.payoutExportedAt || '', complete: true }
    return { exported: !!r.positionsExportedAt, date: r.positionsExportedAt || '', complete: r.positionsComplete }
  }

  // Periods (of the given ids) that the given variant would send to lexoffice a
  // second time — for the duplicate-import confirm before an export starts.
  const alreadyExported = (periodIds: string[], variant: LexofficeExportVariant) => periodIds.filter(id => {
    const r = get(id)
    if (!r) return false
    const positions = variant !== 'payouts' && !!r.positionsExportedAt
    const payout = variant !== 'positions' && !!r.payoutExportedAt
    return positions || payout
  })

  return { periods, available, loading, busy, version, load, record, reset, get, stateOf, badgeOf, rowStatus, alreadyExported }
}
