// Loop 10 (UI-Komponenten zerlegen): geteiltes Fundament der Detail-Sektionen.
//
// Hierhin gezogen aus qaf-comparison-detail.tsx (unverändert, nur verschoben):
// die Zeilen-Typen der persistierten Daten, die de-DE-Formatter, die
// Günstigkeits-Farbe und die kleinen lokalen Bausteine (Field, Badges,
// Listen). KEINE fachliche Berechnung — Formatierung und Darstellung.
// Die frühere KpiTile-Komponente ist entfernt (Loop 10 View-Spec-Adoption):
// sie leitete den Status selbst aus dem Delta ab (ohne neutral-Band) —
// die Überblick-Kacheln rendern jetzt fertige view-specs-KpiTile-Objekte
// über QafV2KpiTile, denselben Renderer wie die V2-Übersicht.
// tdd-guard:skip — presentational; die Regel-Logik (diffDirection,
// productionFieldDelta, …) lebt getestet in lib/ bzw. qaf-diff-status.ts.

import { Badge } from "@/components/ui/badge"
import { Pill } from "@/components/qaf-differences/qaf-section"
import { Tooltip } from "@/components/ui/tooltip"
import { TemplateCoverageContent } from "@/components/qaf-differences/qaf-provenance"
import {
  productionFieldDelta,
  type ProductionStepRates,
} from "@/lib/qaf-differences"
import type { NegotiationRowSpec } from "@/lib/qaf-differences/internal/negotiation-run"
import { sourceRefTitle } from "@/components/qaf-differences/qaf-v2-kpi-tile"
import type { AppendixStructureChange } from "@/lib/qaf-differences/internal/appendix-run"

// Loop 10 Modul 3 (View-Spec-Adoption): die Anhangs-Zeilentypen und die
// Match-Unsicherheits-Regel (UNCERTAIN_MATCH/isUncertainMatch) leben jetzt
// kanonisch im Builder (appendix-run.ts). Re-Export unter den etablierten
// Namen, damit bestehende Importe der Sektions-Module weiter funktionieren.
export type {
  AppendixPlausibility as Plausibility,
  AppendixStepMatch as StepMatch,
  AppendixStructureChange as StructureChange,
} from "@/lib/qaf-differences/internal/appendix-run"

// Loop 10 Modul 4: die Fertigungs-Zeilentypen (qaf_manufacturing_diff/-step
// READ-Shapes) leben kanonisch im Builder (manufacturing-run.ts) — gleiches
// Re-Export-Muster wie die Anhangs-Typen oben.
export type {
  ManufacturingDiff as Diff,
  ManufacturingStepRow as StepRow,
} from "@/lib/qaf-differences/internal/manufacturing-run"

// ── Zeilen-Typen der persistierten Daten (unverändert übernommen) ───────────

export interface Comparison {
  id: string
  comparison_file_id?: string | null
  part_number: string | null
  comparison_mode?: string | null
  baseline_status: string | null
  status: string | null
  created_at: string | null
}
export interface Part {
  part_name: string | null
  supplier: string | null
  variant: string | null
  quotation_date: string | null
}
export interface RootCause {
  management_summary: string | null
  uncertainties: string | null
  top_drivers: unknown
}

/** One workbook-safety advisory finding (KAR-914/P4.4), computed
 * server-side by workbookSafetyToPlausibilityIssues and passed through
 * verbatim — see WorkbookSafetyBadges. */
export interface WorkbookSafetyIssueProp {
  type: string
  explanation: string
  explanationEn?: string | null
}

// ── de-DE-Formatter (unverändert übernommen) ────────────────────────────────

const numFmt = new Intl.NumberFormat("de-DE", { maximumFractionDigits: 2 })
const pctFmt = new Intl.NumberFormat("de-DE", {
  style: "percent",
  maximumFractionDigits: 1,
})
const ppFmt = new Intl.NumberFormat("de-DE", {
  maximumFractionDigits: 1,
  signDisplay: "exceptZero",
})

export function fmtNum(n: number | null): string {
  return n === null || Number.isNaN(n) ? "—" : numFmt.format(n)
}
export function fmtPct(n: number | null): string {
  return n === null || Number.isNaN(n) ? "—" : pctFmt.format(n)
}
export function fmtPp(n: number | null): string {
  return n === null || Number.isNaN(n) ? "—" : `${ppFmt.format(n)} pp`
}
export function fmtDate(iso: string | null): string {
  if (!iso) return "—"
  const d = new Date(iso)
  return Number.isNaN(d.getTime()) ? "—" : d.toLocaleDateString("de-DE")
}

export const pctSignedFmt = new Intl.NumberFormat("de-DE", {
  style: "percent",
  maximumFractionDigits: 1,
  signDisplay: "exceptZero",
})
export const deltaAbsFmt = new Intl.NumberFormat("de-DE", {
  maximumFractionDigits: 2,
  signDisplay: "exceptZero",
})

export function fmtMoney(n: number | null, currency: string | null): string {
  if (n === null || Number.isNaN(n)) return "—"
  try {
    return new Intl.NumberFormat("de-DE", {
      style: "currency",
      currency: currency ?? "EUR",
    }).format(n)
  } catch {
    // Unknown/free-text currency code from the sheet — fall back to number + code.
    return `${numFmt.format(n)}${currency ? ` ${currency}` : ""}`
  }
}

// All summary metrics are costs: an increase is unfavorable (red), a decrease
// favorable (green) — mirrors the V11 tile colouring (rot = teurer).
export function costDeltaColor(delta: number | null): string {
  if (delta === null || delta === 0) return "text-muted-foreground"
  return delta > 0 ? "text-destructive" : "text-success-text"
}

// KAR-966 item 3 — Produktionssicht (§6) ALT/NEU diff highlight. Reuses the
// SAME favourability colour tokens as costDeltaColor/diffStatusClass above
// (unfavorable → text-destructive, favorable → text-success-text) via the
// pure productionFieldDelta classification (lib/qaf-differences); no new
// colour vocabulary. Colour is never the only signal — prodDeltaArrow adds
// a ▲/▼ marker (the SAME symbol diffStatusLabel already uses elsewhere on
// this page) so the change is legible without colour too.
function prodDeltaClass(kind: ReturnType<typeof productionFieldDelta>): string {
  if (kind === "unfavorable") return "text-destructive font-medium"
  if (kind === "favorable") return "text-success-text font-medium"
  return ""
}
function prodDeltaArrow(altVal: number | null, neuVal: number | null): string {
  if (altVal === null || neuVal === null || altVal === neuVal) return ""
  return neuVal > altVal ? " ▲" : " ▼"
}

/** One "ALT / NEU" cell body for the Produktionssicht table — highlights the
 * NEU value when it differs from ALT (KAR-966 item 3). `field` selects the
 * favourability direction via HIGHER_IS_BETTER_FIELDS (through
 * productionFieldDelta); none of this table's fields are in that set today,
 * so an increase always reads unfavorable/red here — passed explicitly
 * rather than hardcoded so a future field addition stays correct. */
export function ProdDeltaPair({
  alt,
  neu,
  field,
  fmt,
}: {
  alt: number | null
  neu: number | null
  field: keyof ProductionStepRates
  fmt: (n: number | null) => string
}) {
  const kind = productionFieldDelta(alt, neu, field)
  return (
    <>
      {fmt(alt)} /{" "}
      <span className={prodDeltaClass(kind)}>
        {fmt(neu)}
        {prodDeltaArrow(alt, neu)}
      </span>
    </>
  )
}

export const BASELINE_LABEL: Record<string, string> = {
  ok: "Baseline OK",
  baseline_review: "Baseline-Review nötig",
  insufficient: "Baseline unzureichend",
}

// ── Kleine Darstellungs-Bausteine (unverändert übernommen) ──────────────────

export function NegotiationList({
  title,
  rows,
  accent,
  currency,
}: {
  title: string
  /** Loop 10 Modul 2: Zeilen tragen SourceRef — das Label zeigt die
   * Belege als Tooltip (EIN Format, sourceRefTitle aus dem Kachel-Renderer). */
  rows: NegotiationRowSpec[]
  accent: string
  currency: string | null
}) {
  return (
    <div className="space-y-2">
      <h3 className={`text-sm font-semibold ${accent}`}>{title}</h3>
      {rows.length === 0 ? (
        <p className="text-xs text-muted-foreground">—</p>
      ) : (
        <ul className="space-y-1.5 text-sm">
          {rows.map((r) => (
            <li key={r.label} className="text-foreground">
              <span className="font-medium" title={sourceRefTitle(r.sourceRef)}>
                {r.label}
              </span>
              :{" "}
              <span className="tabular-nums">
                {fmtMoney(r.alt, currency)} → {fmtMoney(r.neu, currency)}
              </span>{" "}
              <span className={`tabular-nums ${accent}`}>
                ({deltaAbsFmt.format(r.deltaAbsolute)}
                {r.deltaPercent !== null &&
                  ` · ${pctSignedFmt.format(r.deltaPercent)}`}
                )
              </span>
            </li>
          ))}
        </ul>
      )}
    </div>
  )
}

export function Field({
  label,
  value,
  badge,
}: {
  label: string
  value: string | null | undefined
  /** KAR-895/P1.4: optional trailing badge (used for the template
   * known/modified/unknown classification next to ALT/NEU file identity) —
   * additive, every other Field call stays unaffected. */
  badge?: React.ReactNode
}) {
  return (
    <div className="flex justify-between gap-3 border-b border-border/40 py-1">
      <dt className="text-muted-foreground">{label}</dt>
      <dd className="flex items-center justify-end gap-2 text-right font-medium text-foreground">
        {value || "—"}
        {badge}
      </dd>
    </div>
  )
}

// KAR-895/P1.4: known/modified/unknown template classification badge — reuses
// Pill (same primitive as A4. Plausibilität), namespaced label/class
// kept local to the detail sections rather than shared, same precedent as
// qaf-g60-detail.tsx's structureIssueLabel/-Class (avoids touching a
// well-tested shared module for a one-section badge).
const TEMPLATE_CLASSIFICATION_LABEL: Record<string, string> = {
  known: "Bekanntes Template",
  modified: "Template weicht ab",
  unknown: "Unbekanntes Template",
}
function templateClassificationClass(classification: string): string {
  if (classification === "known") return "bg-status-green text-foreground"
  if (classification === "modified") return "bg-status-yellow text-foreground"
  return "bg-status-red-strong text-foreground"
}
function TemplateClassificationBadge({
  classification,
}: {
  classification: string | null | undefined
}) {
  if (!classification) return null
  return (
    <Pill
      label={TEMPLATE_CLASSIFICATION_LABEL[classification] ?? classification}
      className={templateClassificationClass(classification)}
    />
  )
}

// KAR-911/P4.1: wraps TemplateClassificationBadge in a hover/tap tooltip
// showing the per-facet coverage short-form already computed by
// template-fingerprint.ts (deviations/deviationsEn) — renders nothing when
// there is no classification at all (file predates the feature), same guard
// as the plain badge above (no point tooltipping an empty span).
export function TemplateClassificationField({
  classification,
  deviations,
  deviationsEn,
}: {
  classification: string | null | undefined
  deviations: string[]
  deviationsEn: string[]
}) {
  if (!classification) return null
  return (
    <Tooltip
      content={
        <TemplateCoverageContent
          classification={classification}
          deviations={deviations}
          deviationsEn={deviationsEn}
        />
      }
    >
      {/* KAR-915 review rider (PR #290): keyboard-accessible tooltip trigger
       * — a bare <span> is never focusable/reachable by Tab, same fix as
       * WorkbookSafetyBadges (qaf-provenance.tsx). */}
      <button type="button" className="cursor-default">
        <TemplateClassificationBadge classification={classification} />
      </button>
    </Tooltip>
  )
}

// KAR-905/P3.1 — per-file DE/EN/mixed language badge, same Pill primitive and
// "namespaced label/class kept local" precedent as
// TemplateClassificationBadge above. Renders nothing for null/undefined
// (file predates this feature) — but DOES render for 'unknown' (a real,
// meaningful detector outcome: "no DE/EN signal found", distinct from "not
// computed at all"), same "absence vs. explicit unknown" distinction
// template-fingerprint.ts's own module header draws for classification.
const LANGUAGE_BADGE_LABEL: Record<string, string> = {
  de: "DE",
  en: "EN",
  mixed: "DE/EN gemischt",
  unknown: "Sprache unbekannt",
}
function languageBadgeClass(language: string): string {
  if (language === "mixed") return "bg-status-yellow text-foreground"
  if (language === "unknown") return "bg-status-grey text-foreground"
  return "bg-status-green text-foreground"
}
export function LanguageBadge({
  language,
}: {
  language: string | null | undefined
}) {
  if (!language) return null
  return (
    <Pill
      label={LANGUAGE_BADGE_LABEL[language] ?? language}
      className={languageBadgeClass(language)}
    />
  )
}

export function StructureList({
  title,
  steps,
  pillClass,
}: {
  title: string
  steps: AppendixStructureChange[]
  pillClass: string
}) {
  return (
    <div className="space-y-2">
      <div className="flex items-center gap-2">
        <Pill label={title} className={pillClass} />
        <span className="text-xs text-muted-foreground">{steps.length}</span>
      </div>
      {steps.length === 0 ? (
        <p className="text-xs text-muted-foreground">—</p>
      ) : (
        <ul className="space-y-1 text-sm text-foreground">
          {steps.map((s, i) => (
            <li key={i}>{s.step_label || s.detail || "—"}</li>
          ))}
        </ul>
      )}
    </div>
  )
}

// Wird von OverviewSection gebraucht — hier re-exportiert, damit die
// Sektions-Module ihre Badge-Primitive aus EINER Stelle beziehen.
export { Badge }
