"use client";

import { useEffect, useState } from "react";
import { CartesianGrid, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
import { TOOLTIP_STYLE } from "@/components/AllocationChart";
import { formatChf } from "@/lib/format";
import type { PlanComputed } from "@/lib/calculations";

export interface TimelineSeries {
  // Eindeutiger Schlüssel der Serie. WICHTIG: Bis 0.30 diente der ANZEIGENAME als Datenschlüssel
  // -- zwei Szenarien mit gleichem Namen überschrieben sich dadurch gegenseitig (die Legende
  // zeigte beide, der Chart nur eine). Deshalb ein eigener, garantiert eindeutiger Schlüssel.
  id: string;
  label: string;
  color: string;
  computed: PlanComputed;
  // Plandaten werden gestrichelt gezeichnet, effektive Daten durchgezogen. Das Stilbudget
  // geht bewusst an Plan/Ist statt an nominal/real (siehe SPEZIFIKATION 9.29).
  dashed?: boolean;
}

// Datenpunkte je Serie: JEDES Planjahr (nicht nur die Phasengrenzen), verortet auf dem Alter
// der Referenzperson (Person A). Der erste Punkt ist das Startvermögen vor Jahr 1.
function pointsFor(computed: PlanComputed) {
  const phases = computed.phases;
  if (phases.length === 0) return [] as { age: number; nominal: number; real: number }[];
  const startAge = phases[0].persons[0]?.startAge ?? 0;
  const start = Math.round(phases[0].startWealthNominal);
  const pts = [{ age: startAge, nominal: start, real: start }];
  for (const y of computed.yearly) {
    pts.push({ age: y.age, nominal: y.wealthNominal, real: y.wealthReal });
  }
  return pts;
}

// `var(--chart-1)` in einen konkreten Hex-Wert auflösen -- das Farbwahl-Feld (input[type=color])
// braucht einen echten Wert. Läuft nur im Browser und nur, wenn eine Variable übergeben wurde.
function resolveColor(color: string): string {
  if (!color.startsWith("var(")) return color;
  if (typeof window === "undefined") return "#888888";
  const name = color.slice(4, -1).trim();
  const v = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
  return v || "#888888";
}

// Liniendiagramm: Gesamtvermögen (nominal + real) über das Alter. Unterstützt mehrere
// überlagerte Pläne für den Szenario-Vergleich.
export function WealthChart({
  series,
  metric = "nominal",
  onColorChange,
}: {
  series: TimelineSeries[];
  metric?: "nominal" | "real";
  // Optional: erlaubt das Umfärben einer Serie über die Legende.
  onColorChange?: (id: string, color: string) => void;
}) {
  // Aufgelöste Farben für die Farbwahl-Felder; nach dem ersten Rendern (und bei Theme-Wechsel).
  const [resolved, setResolved] = useState<Record<string, string>>({});
  const colorKey = series.map((s) => `${s.id}:${s.color}`).join("|");
  useEffect(() => {
    const next: Record<string, string> = {};
    for (const s of series) next[s.id] = resolveColor(s.color);
    // eslint-disable-next-line react-hooks/set-state-in-effect -- Farbauflösung braucht das DOM
    setResolved(next);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [colorKey]);

  if (series.length === 0 || series[0].computed.phases.length === 0) {
    return <p className="text-sm text-muted">Noch keine Phasen vorhanden.</p>;
  }

  const withPoints = series.map((s) => ({ ...s, points: pointsFor(s.computed) }));
  const ages = Array.from(new Set(withPoints.flatMap((s) => s.points.map((p) => p.age)))).sort((a, b) => a - b);

  const data = ages.map((age) => {
    const row: Record<string, number | null> = { age };
    for (const s of withPoints) {
      const pt = s.points.find((p) => p.age === age);
      row[s.id] = pt ? (metric === "real" ? pt.real : pt.nominal) : null;
    }
    return row;
  });

  const nameById = new Map(series.map((s) => [s.id, s.label]));
  const hasDashed = series.some((s) => s.dashed);

  return (
    <div className="w-full">
      <div className="h-80 w-full">
        <ResponsiveContainer width="100%" height="100%">
          <LineChart data={data} margin={{ top: 8, right: 16, left: 8, bottom: 8 }}>
            <CartesianGrid strokeDasharray="3 3" stroke="var(--chart-grid)" />
            <XAxis
              dataKey="age"
              type="number"
              domain={["dataMin", "dataMax"]}
              tick={{ fontSize: 11 }}
              stroke="var(--faint)"
              tickFormatter={(v) => `${v} J.`}
            />
            <YAxis
              tick={{ fontSize: 11 }}
              stroke="var(--faint)"
              tickFormatter={(v) => Intl.NumberFormat("de-CH", { notation: "compact" }).format(v)}
            />
            <Tooltip
              contentStyle={TOOLTIP_STYLE}
              formatter={(v, key) => [typeof v === "number" ? formatChf(v) : v, nameById.get(String(key)) ?? key]}
              labelFormatter={(v) => `Alter ${v}`}
            />
            {withPoints.map((s) => (
              <Line
                key={s.id}
                type="monotone"
                dataKey={s.id}
                name={s.label}
                stroke={s.color}
                strokeWidth={2}
                strokeDasharray={s.dashed ? "5 3" : undefined}
                dot={false}
                connectNulls
                isAnimationActive={false}
              />
            ))}
          </LineChart>
        </ResponsiveContainer>
      </div>

      {/* Eigene Legende statt der von Recharts: Sie trägt die Farbwahl und erklärt den
          Linienstil -- ohne das wäre unklar, wofür die gestrichelte Linie steht. */}
      <div className="mt-2 flex flex-wrap items-center gap-x-4 gap-y-1.5">
        {series.map((s) => (
          <span key={s.id} className="flex items-center gap-1.5 text-xs text-muted">
            {onColorChange ? (
              <label className="relative flex cursor-pointer items-center" title="Farbe wählen">
                <span
                  className="block h-3 w-6 rounded-sm"
                  style={{
                    background: s.dashed
                      ? `repeating-linear-gradient(90deg, ${s.color} 0 5px, transparent 5px 8px)`
                      : s.color,
                  }}
                />
                <input
                  type="color"
                  value={resolved[s.id] ?? "#888888"}
                  onChange={(e) => onColorChange(s.id, e.target.value)}
                  className="absolute inset-0 h-full w-full cursor-pointer opacity-0"
                />
              </label>
            ) : (
              <span
                className="block h-3 w-6 rounded-sm"
                style={{
                  background: s.dashed
                    ? `repeating-linear-gradient(90deg, ${s.color} 0 5px, transparent 5px 8px)`
                    : s.color,
                }}
              />
            )}
            {s.label}
          </span>
        ))}
        {hasDashed && (
          <span className="text-[11px] text-faint">
            gestrichelt = reine Planwerte · durchgezogen = mit effektiven Werten
          </span>
        )}
      </div>
    </div>
  );
}
