'use client'

// Section 4 "Material-Vergleich" of the Multi-QAF detail view (KAR-947) —
// the two-level material comparison Master-Prompt §11 requires: Section
// 11.1 (shared-component-level) findings render as ONE finding per shared
// change with its affected-variant impact list, never duplicated per
// variant (material-differ.ts's own KERN-REGEL); Section 11.2
// (variant-allocation-level) findings render below that. Client component
// because it owns the Kostenart/Richtung/Ebene filter state (task
// requirement 6) — every other Multi-QAF section is a plain server-rendered
// composition (see qaf-multi-qaf-detail.tsx).
// tdd-guard:skip — presentational filter/render composition over an
// already-computed, already-unit-tested MaterialDiffResult (material-differ.ts).

import { useMemo, useState, type ReactNode } from 'react'
import { moneyFormatter } from '@/components/qaf-differences/format'
import { Pill } from '@/components/qaf-differences/qaf-section'
import { MultiQafSourceRefs } from '@/components/qaf-differences/qaf-multi-qaf-source-refs'
import { QafMultiQafMaterialCostDriverChart } from '@/components/qaf-differences/qaf-multi-qaf-material-chart'
import { STATUS_TAXONOMY_CLASS } from '@/components/qaf-differences/qaf-multi-qaf-status-taxonomy'
import type {
  DiffStatus,
  MaterialDiffResult,
  MaterialComponentRef,
  SharedComponentImpactSummary,
  VariantAllocationFinding,
} from '@/lib/qaf-differences'

type MoneyFormatter = ReturnType<typeof moneyFormatter>
const fmtCache = new Map<string, MoneyFormatter>()
function fmtFor(currency: string | null): MoneyFormatter {
  const key = currency ?? '∅'
  let f = fmtCache.get(key)
  if (!f) {
    f = moneyFormatter(currency)
    fmtCache.set(key, f)
  }
  return f
}

const STATUS_LABEL: Partial<Record<DiffStatus, string>> = {
  neu: 'Neu',
  entfallen: 'Entfallen',
  konstant: 'Konstant',
  anstieg: 'Anstieg',
  senkung: 'Senkung',
  nicht_berechenbar: 'Nicht berechenbar',
  nicht_anwendbar: 'Nicht anwendbar',
}
function statusClass(status: DiffStatus | null): string {
  if (status === 'anstieg') return STATUS_TAXONOMY_CLASS.blocked
  if (status === 'senkung') return STATUS_TAXONOMY_CLASS.ok
  if (status === 'neu') return 'bg-primary-tint text-primary'
  if (status === 'entfallen') return STATUS_TAXONOMY_CLASS.neutral
  return 'bg-muted text-muted-foreground'
}
function direction(status: DiffStatus | null): 'increase' | 'decrease' | 'other' {
  if (status === 'anstieg') return 'increase'
  if (status === 'senkung') return 'decrease'
  return 'other'
}
function StatusPill({ status }: { status: DiffStatus | null }) {
  if (!status) return null
  return <Pill label={STATUS_LABEL[status] ?? status} className={statusClass(status)} />
}

function refLabel(ref: MaterialComponentRef): ReactNode {
  return (
    <span className="inline-flex items-center">
      <span className="font-mono text-xs">{ref.canonicalComponentIdentity}</span>
      <MultiQafSourceRefs refs={ref.sourceCells} />
    </span>
  )
}

function ImpactSummary({ impact }: { impact: SharedComponentImpactSummary }) {
  if (impact.affectedVariantIds.length === 0) return null
  return (
    <div className="mt-1 space-y-1 text-xs text-muted-foreground">
      <p>
        Betroffene Varianten ({impact.affectedVariantIds.length}):{' '}
        {impact.impacts.map((imp, i) => (
          <span key={imp.variantId} className="mr-2 inline-block">
            <span className="font-mono">{imp.variantId}</span>
            {imp.impact !== null ? (
              <span className={imp.impact > 0 ? 'text-destructive' : imp.impact < 0 ? 'text-success-text' : ''}>
                {' '}
                {fmtFor(imp.currency)(imp.impact)}
              </span>
            ) : (
              <span className="italic"> — nicht berechenbar ({imp.reason ?? 'unbekannt'})</span>
            )}
            {i < impact.impacts.length - 1 ? ';' : ''}
          </span>
        ))}
      </p>
      {impact.aggregates.length > 0 && (
        <p className="font-medium text-foreground">
          Aggregat je Währung:{' '}
          {impact.aggregates.map((a) => (
            <span key={a.currency} className="mr-2">
              {fmtFor(a.currency)(a.totalImpact)} ({a.variantCount} Var.)
            </span>
          ))}
        </p>
      )}
    </div>
  )
}

interface FilterRow {
  id: string
  category: MaterialCategory
  level: 'shared' | 'variant'
  status: DiffStatus | null
  reviewRelevant: boolean
  node: ReactNode
}

const CATEGORY_LABEL = {
  unitCostValue: 'Einheitskosten',
  unitCostCurrency: 'Währung',
  exchangeRate: 'Wechselkurs',
  logisticsOrDuty: 'Logistik/Zoll',
  materialOverhead: 'Materialgemeinkosten',
  formula: 'Formel',
  rowIdentity: 'Positions-Identität',
  allocation: 'Varianten-Zuordnung',
  substitution: 'Substitutionsverdacht',
} as const
type MaterialCategory = keyof typeof CATEGORY_LABEL

const ALLOCATION_KIND_LABEL: Record<VariantAllocationFinding['kind'], string> = {
  factor_changed: 'Faktor geändert',
  included: 'neu einbezogen',
  excluded: 'ausgeschlossen',
  component_added: 'Komponente hinzugefügt',
  component_removed: 'Komponente entfernt',
}

function buildRows(diff: MaterialDiffResult): FilterRow[] {
  const rows: FilterRow[] = []

  for (const f of diff.sharedComponents.unitCostValueChanges) {
    rows.push({
      id: `ucv:${f.canonicalComponentIdentity}`,
      category: 'unitCostValue',
      level: 'shared',
      status: f.status,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`ucv:${f.canonicalComponentIdentity}`} className="rounded border border-border p-2">
          {refLabel(f.neu)} <StatusPill status={f.status} />
          <span className="ml-2 text-sm">
            {f.altValue ?? '—'} → {f.neuValue ?? '—'}
            {f.deltaPercent !== null && <span className="ml-1 text-muted-foreground">({(f.deltaPercent * 100).toFixed(1)} %)</span>}
          </span>
          {f.reviewRelevant && <Pill label="Review" className={`ml-2 ${STATUS_TAXONOMY_CLASS.attention}`} />}
          <ImpactSummary impact={f.impact} />
        </li>
      ),
    })
  }
  for (const f of diff.sharedComponents.unitCostCurrencyChanges) {
    rows.push({
      id: `ucc:${f.canonicalComponentIdentity}`,
      category: 'unitCostCurrency',
      level: 'shared',
      status: null,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`ucc:${f.canonicalComponentIdentity}`} className="rounded border border-border p-2">
          {refLabel(f.neu)} <span className="ml-2 text-sm">{f.altCurrency ?? '—'} → {f.neuCurrency ?? '—'}</span>
          <Pill label="Review" className={`ml-2 ${STATUS_TAXONOMY_CLASS.attention}`} />
          <ImpactSummary impact={f.impact} />
        </li>
      ),
    })
  }
  for (const f of diff.sharedComponents.exchangeRateChanges) {
    rows.push({
      id: `xr:${f.canonicalComponentIdentity}`,
      category: 'exchangeRate',
      level: 'shared',
      status: f.status,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`xr:${f.canonicalComponentIdentity}`} className="rounded border border-border p-2">
          {refLabel(f.neu)} <StatusPill status={f.status} />
          <span className="ml-2 text-sm">
            {f.altValue ?? '—'} → {f.neuValue ?? '—'}
          </span>
          <ImpactSummary impact={f.impact} />
        </li>
      ),
    })
  }
  for (const f of diff.sharedComponents.logisticsOrDutyChanges) {
    rows.push({
      id: `lod:${f.canonicalComponentIdentity}`,
      category: 'logisticsOrDuty',
      level: 'shared',
      status: f.status,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`lod:${f.canonicalComponentIdentity}`} className="rounded border border-border p-2">
          {refLabel(f.neu)} <StatusPill status={f.status} />
          <span className="ml-2 text-sm">
            {f.altAmount ? fmtFor(f.altAmount.currency)(f.altAmount.value ?? 0) : '—'} →{' '}
            {f.neuAmount ? fmtFor(f.neuAmount.currency)(f.neuAmount.value ?? 0) : '—'}
          </span>
          {f.currencyChanged && <Pill label="Währung geändert" className={`ml-2 ${STATUS_TAXONOMY_CLASS.attention}`} />}
          <ImpactSummary impact={f.impact} />
        </li>
      ),
    })
  }
  for (const f of diff.sharedComponents.materialOverheadChanges) {
    rows.push({
      id: `mo:${f.canonicalComponentIdentity}`,
      category: 'materialOverhead',
      level: 'shared',
      status: f.status,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`mo:${f.canonicalComponentIdentity}`} className="rounded border border-border p-2">
          {refLabel(f.neu)} <StatusPill status={f.status} />
          <span className="ml-2 text-sm">
            {f.altAmount ? fmtFor(f.altAmount.currency)(f.altAmount.value ?? 0) : '—'} →{' '}
            {f.neuAmount ? fmtFor(f.neuAmount.currency)(f.neuAmount.value ?? 0) : '—'}
          </span>
          <ImpactSummary impact={f.impact} />
        </li>
      ),
    })
  }
  for (const f of diff.sharedComponents.formulaChanges) {
    rows.push({
      id: `fc:${f.canonicalComponentIdentity}`,
      category: 'formula',
      level: 'shared',
      status: null,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`fc:${f.canonicalComponentIdentity}`} className="rounded border border-border p-2">
          {refLabel(f.neu)} <Pill label={f.comparisonKind} className={`ml-2 ${STATUS_TAXONOMY_CLASS.attention}`} />
          <p className="mt-0.5 text-sm text-muted-foreground">{f.explanation}</p>
          <ImpactSummary impact={f.impact} />
        </li>
      ),
    })
  }
  for (const f of diff.sharedComponents.rowIdentityChanges) {
    rows.push({
      id: `ri:${f.altCanonicalComponentIdentity}`,
      category: 'rowIdentity',
      level: 'shared',
      status: null,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`ri:${f.altCanonicalComponentIdentity}`} className="rounded border border-border p-2">
          Pos. {f.position}: {f.altLabel} → {f.neuLabel}
          {refLabel(f.neu)}
        </li>
      ),
    })
  }

  for (const f of diff.variantAllocation.findings) {
    rows.push({
      id: `alloc:${f.canonicalComponentIdentity}:${f.altVariantId}:${f.neuVariantId}`,
      category: 'allocation',
      level: 'variant',
      status: f.effectiveCostStatus,
      reviewRelevant: f.reviewRelevant,
      node: (
        <li key={`alloc:${f.canonicalComponentIdentity}:${f.altVariantId}:${f.neuVariantId}`} className="rounded border border-border p-2">
          <span className="font-mono text-xs">{f.canonicalComponentIdentity}</span>{' '}
          <Pill label={ALLOCATION_KIND_LABEL[f.kind]} className="bg-muted text-foreground" />{' '}
          <span className="font-mono text-xs text-muted-foreground">
            {f.altVariantId} → {f.neuVariantId}
          </span>
          <StatusPill status={f.effectiveCostStatus} />
          <span className="ml-2 text-sm">
            Faktor {f.altFactor ?? '—'} → {f.neuFactor ?? '—'}
          </span>
          {f.effectiveCostDeltaReason === 'mixed_currency' && (
            <p className="text-xs italic text-muted-foreground">Delta nicht berechenbar — abweichende Währungen.</p>
          )}
          {f.reviewRelevant && <Pill label="Review" className={`ml-2 ${STATUS_TAXONOMY_CLASS.attention}`} />}
        </li>
      ),
    })
  }
  for (const f of diff.variantAllocation.substitutionsSuspected) {
    rows.push({
      id: `sub:${f.removed.canonicalComponentIdentity}`,
      category: 'substitution',
      level: 'variant',
      status: null,
      reviewRelevant: true,
      node: (
        <li key={`sub:${f.removed.canonicalComponentIdentity}`} className="rounded border border-border p-2">
          <span className="font-mono text-xs">{f.removed.canonicalComponentIdentity}</span> könnte ersetzt worden sein durch:{' '}
          {f.addedCandidates.map((c) => (
            <span key={c.canonicalComponentIdentity} className="ml-1 font-mono text-xs">
              {c.canonicalComponentIdentity}
            </span>
          ))}
          <span className="ml-2 text-xs text-muted-foreground">(Ähnlichkeit {Math.round(f.labelSimilarity * 100)} %)</span>
          <Pill label="Review — nie automatisch" className={`ml-2 ${STATUS_TAXONOMY_CLASS.attention}`} />
        </li>
      ),
    })
  }

  return rows
}

export function QafMultiQafMaterialSection({ diff }: { diff: MaterialDiffResult }) {
  const [categories, setCategories] = useState<Set<MaterialCategory>>(new Set(Object.keys(CATEGORY_LABEL) as MaterialCategory[]))
  const [dir, setDir] = useState<'all' | 'increase' | 'decrease'>('all')
  const [level, setLevel] = useState<'all' | 'shared' | 'variant'>('all')

  const rows = useMemo(() => buildRows(diff), [diff])
  const filtered = rows.filter((r) => {
    if (!categories.has(r.category)) return false
    if (level !== 'all' && r.level !== level) return false
    if (dir !== 'all' && direction(r.status) !== dir) return false
    return true
  })

  function toggleCategory(c: MaterialCategory) {
    setCategories((prev) => {
      const next = new Set(prev)
      if (next.has(c)) next.delete(c)
      else next.add(c)
      return next
    })
  }

  const uncertain = diff.uncertainMatches.length

  return (
    <div className="space-y-3">
      <QafMultiQafMaterialCostDriverChart diff={diff} />
      <div className="flex flex-wrap items-center gap-1.5 print:hidden">
        {(Object.keys(CATEGORY_LABEL) as MaterialCategory[]).map((c) => (
          <button
            key={c}
            type="button"
            onClick={() => toggleCategory(c)}
            className={`rounded border px-2 py-0.5 text-xs ${
              categories.has(c) ? 'border-primary bg-primary/10 text-foreground' : 'border-border text-muted-foreground hover:text-foreground'
            }`}
          >
            {CATEGORY_LABEL[c]}
          </button>
        ))}
      </div>
      <div className="flex flex-wrap items-center gap-3 text-xs print:hidden">
        <span className="flex items-center gap-1">
          {(['all', 'increase', 'decrease'] as const).map((d) => (
            <button
              key={d}
              type="button"
              onClick={() => setDir(d)}
              className={`rounded border px-2 py-0.5 ${dir === d ? 'border-primary bg-primary/10 text-foreground' : 'border-border text-muted-foreground'}`}
            >
              {d === 'all' ? 'Alle' : d === 'increase' ? 'Erhöhung' : 'Reduktion'}
            </button>
          ))}
        </span>
        <span className="flex items-center gap-1">
          {(['all', 'shared', 'variant'] as const).map((l) => (
            <button
              key={l}
              type="button"
              onClick={() => setLevel(l)}
              className={`rounded border px-2 py-0.5 ${level === l ? 'border-primary bg-primary/10 text-foreground' : 'border-border text-muted-foreground'}`}
            >
              {l === 'all' ? 'Alle Ebenen' : l === 'shared' ? 'Gemeinsam' : 'Varianten-spezifisch'}
            </button>
          ))}
        </span>
      </div>

      {uncertain > 0 && (
        <p className="text-xs text-amber-700 dark:text-amber-400">
          {uncertain} Varianten-Zuordnung(en) unsicher — Material-Impact für diese Varianten hier nicht mitgerechnet (siehe Sektion 2).
        </p>
      )}

      {filtered.length === 0 ? (
        <p className="text-sm text-muted-foreground">Keine Befunde für die aktuelle Filterauswahl.</p>
      ) : (
        <ul className="space-y-1.5">{filtered.map((r) => r.node)}</ul>
      )}
    </div>
  )
}
