"use client";

import { useEffect, useMemo, useRef, useState, type ReactElement, type CSSProperties } from "react";

type DurationPoint = { dateISO: string; ms: number };

type SuccessStatsProps = {
  displayName: string;
  days: number;
  percent: number;
  totalDays: number;
  currentDurationMs: number | null;
  averageDurationMs: number | null;
  bestDurationMs: number | null;
  durationSeries: DurationPoint[];
  measurementCount: number;
  showShortPasswordAlert: boolean;
  shortPasswordMessage: string;
  metricSuffix: string;
  currentSubtitle: string;
  chartTitle: string;
  isPasswordShort: boolean;
  passwordPolicyViolation: boolean;
  passwordLength: number;
  passwordHasUpper: boolean;
  passwordHasLower: boolean;
  passwordHasDigit: boolean;
  passwordHasSpecial: boolean;
  policyMinLength: number;
};

const dateFormatter = new Intl.DateTimeFormat("de-DE", {
  day: "2-digit",
  month: "2-digit",
  timeZone: "UTC",
});

const disqualStampWrapperStyle: CSSProperties = {
  position: "absolute",
  top: "24px",
  left: "50%",
  transform: "translateX(-50%) rotate(-12deg)",
  pointerEvents: "none",
  zIndex: 50,
};

const disqualStampStyle: CSSProperties = {
  position: "relative",
  display: "inline-flex",
  alignItems: "center",
  justifyContent: "center",
  minWidth: "360px",
  padding: "18px 54px",
  border: "5px solid rgba(239,68,68,0.95)",
  background: "rgba(220,38,38,0.18)",
  color: "#fee2e2",
  fontSize: "1.25rem",
  fontWeight: 900,
  letterSpacing: "0.58em",
  textTransform: "uppercase",
  textShadow: "0 16px 38px rgba(220,38,38,0.6)",
  boxShadow: "0 20px 46px rgba(220,38,38,0.4)",
  whiteSpace: "nowrap",
};

const disqualStampInnerStyle: CSSProperties = {
  position: "absolute",
  inset: "6px",
  border: "2px dashed rgba(248,113,113,0.7)",
};

export default function SuccessStats({
  displayName,
  days,
  percent,
  totalDays,
  currentDurationMs,
  averageDurationMs,
  bestDurationMs,
  durationSeries,
  measurementCount,
  showShortPasswordAlert,
  shortPasswordMessage,
  metricSuffix,
  currentSubtitle,
  chartTitle,
  isPasswordShort,
  passwordPolicyViolation,
  passwordLength,
  passwordHasUpper,
  passwordHasLower,
  passwordHasDigit,
  passwordHasSpecial,
  policyMinLength,
}: SuccessStatsProps): ReactElement {
  const [dAnim, setDAnim] = useState(0);
  const [pAnim, setPAnim] = useState(0);
  const cardRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    animateTo(days, setDAnim, 800);
    animateTo(percent, setPAnim, 900);
    cardRef.current?.animate(
      [
        { boxShadow: "0 10px 32px rgba(0,0,0,.45)" },
        { boxShadow: "0 16px 40px rgba(89,240,168,.18)" },
        { boxShadow: "0 10px 32px rgba(0,0,0,.45)" },
      ],
      { duration: 800, easing: "ease-in-out" }
    );
  }, [days, percent]);

  const hasMeasurements = measurementCount > 0;
  const hasAverage = averageDurationMs !== null;
  const currentTone = useMemo(() => {
    if (!hasAverage || currentDurationMs === null) return "neutral" as const;
    if (currentDurationMs > averageDurationMs!) return "slower" as const;
    if (currentDurationMs < averageDurationMs!) return "faster" as const;
    return "neutral" as const;
  }, [hasAverage, currentDurationMs, averageDurationMs]);
  const chartStats = useMemo(() => {
    if (!hasMeasurements) return null;
    const values = durationSeries.map((point) => point.ms);
    const max = Math.max(...values);
    const min = Math.min(...values);
    return { max, min };
  }, [durationSeries, hasMeasurements]);

  const passwordChecks = useMemo(() => {
    const lengthOk = passwordLength >= policyMinLength;
    const upperOk = passwordHasUpper;
    const lowerOk = passwordHasLower;
    const digitOk = passwordHasDigit;
    const specialOk = passwordHasSpecial;
    return {
      lengthOk,
      upperOk,
      lowerOk,
      digitOk,
      specialOk,
      allOk: lengthOk && upperOk && lowerOk && digitOk && specialOk,
    };
  }, [passwordLength, passwordHasUpper, passwordHasLower, passwordHasDigit, passwordHasSpecial, policyMinLength]);

  const stampNode = passwordPolicyViolation ? (
    <div aria-hidden="true" style={disqualStampWrapperStyle}>
      <div style={disqualStampStyle}>
        <span style={disqualStampInnerStyle} />
        <span style={{ position: "relative", display: "inline-block" }}>Disqualifiziert</span>
      </div>
    </div>
  ) : null;

  const headerNode = (
    <div className="dw-stack">
      <h1
        className={`text-3xl md:text-4xl font-extrabold tracking-wide ${passwordPolicyViolation ? "text-red-200" : ""}`}
        style={{ color: passwordPolicyViolation ? undefined : "var(--dw-accent)" }}
      >
        {passwordPolicyViolation
          ? "Login erfolgreich, aber das Passwort ist nicht gut!"
          : "Login erfolgreich!"}
      </h1>
      <p className={`dw-hint ${passwordPolicyViolation ? "text-red-200/80" : ""}`}>
        {isPasswordShort ? "Dein Passwort ist zu kurz" : "Gut gemacht"},{" "}
        <span className="font-mono glow-red">{displayName}</span>.
      </p>
    </div>
  );

  const alertNode = showShortPasswordAlert ? (
    <div className="dw-alert dw-alert--warn" role="alert">
      {shortPasswordMessage}
    </div>
  ) : null;

  const passwordTile = (
    <div
      className="dw-tile space-y-2"
      style={{
        textAlign: "left",
        borderColor: passwordChecks.allOk ? undefined : "rgba(248,113,113,0.4)",
        background: passwordChecks.allOk ? "linear-gradient(180deg, rgba(255,255,255,.02), rgba(255,255,255,.01))" : "rgba(248,113,113,0.08)",
      }}
    >
      <div className="dw-tile-title">Passwort-Check</div>
      <div className="mt-2 flex flex-col gap-2">
        <SecurityRow
          ok={passwordChecks.lengthOk}
          label={`Passwort-Länge ≥ ${policyMinLength} Zeichen`}
        />
        <SecurityRow ok={passwordChecks.upperOk} label="Großbuchstaben" />
        <SecurityRow ok={passwordChecks.lowerOk} label="Kleinbuchstaben" />
        <SecurityRow ok={passwordChecks.digitOk} label="Ziffern" />
        <SecurityRow ok={passwordChecks.specialOk} label="Sonderzeichen" />
      </div>
      <p className="mt-4 text-xs uppercase tracking-widest text-emerald-100/60">
        {passwordChecks.allOk
          ? "Starke Passwort-Anforderungen erfüllt."
          : "Bitte verbessere dein Passwort, um alle Kriterien zu erfüllen."}
      </p>
    </div>
  );

  if (passwordPolicyViolation) {
    return (
      <div ref={cardRef} className="relative dw-stack dw-stack-lg" style={{ paddingTop: "120px" }}>
        {stampNode}
        {headerNode}
        {alertNode}
        <div className="dw-stats-layout">
          {passwordTile}
        </div>
        <div className="flex items-center gap-2 pt-1">
          <a href="/login" className="dw-btn dw-btn-ghost">Zurück zum Login</a>
        </div>
      </div>
    );
  }

  return (
    <div ref={cardRef} className="relative dw-stack dw-stack-lg">
      {stampNode}
      {headerNode}
      {alertNode}
      <div className="dw-stats-layout">
        <div className="dw-tiles dw-stats-tiles">
          <div className="dw-tile">
            <div className="dw-tile-title">Letzte {totalDays} Tage</div>
            <div className="dw-tile-number" aria-live="polite">{dAnim}</div>
            <div className="dw-tile-sub">{dAnim === 1 ? "Tag mit Erfolg" : "Tage mit Erfolg"}</div>
          </div>
          <div className="dw-tile">
            <div className="dw-tile-title">Rating</div>
            <div className="dw-tile-number" aria-live="polite">{pAnim}%</div>
            <div className="dw-tile-sub">Durchhaltequote</div>
          </div>
          <div className="dw-tile">
            <div className="dw-tile-title">Aktueller Login</div>
            <div
              className={`dw-tile-number ${currentTone === "faster" ? "dw-tile-number--better" : ""}${currentTone === "slower" ? " dw-tile-number--slower" : ""}`}
              aria-live="polite"
            >
              {renderDuration(currentDurationMs, metricSuffix)}
            </div>
            <div className="dw-tile-sub">{currentSubtitle}</div>
            {bestDurationMs !== null && (
              <div className="dw-tile-peer">Deine Bestzeit: {renderDuration(bestDurationMs, metricSuffix)}</div>
            )}
          </div>
          {passwordTile}
        </div>
        <section className="dw-stack dw-stats-chart">
          <header className="flex flex-wrap items-end gap-2">
            <h2 className="text-base font-semibold uppercase tracking-wide text-emerald-200">
              {chartTitle}
            </h2>
            <span className="text-xs text-emerald-100/70">
              Werte in Sekunden{metricSuffix ? ` ${metricSuffix}` : ""},{" "}
              {measurementCount === 1 ? "1 Messung" : `${measurementCount} Messungen`}
            </span>
          </header>
          {hasMeasurements && chartStats ? (
            <DurationChart
              series={durationSeries}
              minMs={chartStats.min}
              maxMs={chartStats.max}
              valueSuffix={metricSuffix}
            />
          ) : (
            <p className="text-sm text-emerald-100/70">
              Noch keine Messwerte vorhanden. Melde dich erneut an, um Daten zu sammeln.
            </p>
          )}
        </section>
      </div>
      <div className="flex items-center gap-2 pt-1">
        <a href="/login" className="dw-btn dw-btn-ghost">Zurück zum Login</a>
      </div>
    </div>
  );
}

function animateTo(target: number, set: (v: number) => void, duration = 800): void {
  const start = performance.now();
  const from = 0;
  const to = Math.max(0, Math.round(target));
  const ease = (t: number): number => 1 - Math.pow(1 - t, 3);
  function frame(now: number): void {
    const p = Math.min(1, (now - start) / duration);
    const val = Math.round(from + (to - from) * ease(p));
    set(val);
    if (p < 1) requestAnimationFrame(frame);
  }
  requestAnimationFrame(frame);
}

function formatDuration(ms: number | null): string {
  if (ms === null || ms === undefined) return "–";
  const seconds = ms / 1000;
  if (seconds < 60) {
    return `${seconds.toFixed(seconds < 10 ? 2 : 1)} s`;
  }
  const minutes = Math.floor(seconds / 60);
  const rest = seconds - minutes * 60;
  const restStr = rest >= 10 ? rest.toFixed(0) : rest.toFixed(1);
  return `${minutes} min ${restStr} s`;
}

function renderDuration(ms: number | null, suffix = ""): ReactElement {
  if (ms === null || ms === undefined) return <>–</>;
  return (
    <>
      <span>{formatDuration(ms)}</span>
      {suffix && <span className="ml-1 align-baseline text-xs uppercase tracking-widest">{suffix}</span>}
    </>
  );
}

function SecurityRow({ ok, label }: { ok: boolean; label: string }): ReactElement {
  return (
    <div className="flex items-center gap-2 text-sm">
      <span className={ok ? "text-emerald-300" : "text-red-300"}>{ok ? "✅" : "🚨"}</span>
      <span className={ok ? "text-emerald-100" : "text-red-100"}>{label}</span>
    </div>
  );
}

function DurationChart({
  series,
  minMs,
  maxMs,
  valueSuffix,
}: {
  series: DurationPoint[];
  minMs: number;
  maxMs: number;
  valueSuffix: string;
}): ReactElement {
  const padding = 8;
  const width = 100;
  const height = 80;
  const usableWidth = width - padding * 2;
  const usableHeight = height - padding * 2;
  const range = Math.max(1, maxMs - minMs);

  const points = series.map((entry, index) => {
    const x = series.length === 1
      ? width / 2
      : padding + (usableWidth * index) / (series.length - 1);
    const y = height - (padding + ((entry.ms - minMs) / range) * usableHeight);
    return { ...entry, x, y };
  });

  const polyline = points.length === 1
    ? `${points[0].x},${points[0].y}`
    : points.map((p) => `${p.x},${p.y}`).join(" ");

  return (
    <div className="w-full overflow-hidden rounded-xl border border-emerald-400/20 bg-[#08111f] px-3 py-4">
      <svg
        viewBox={`0 0 ${width} ${height}`}
        role="img"
        aria-label="Verlauf der Login-Zeiten"
        className="h-40 w-full"
      >
        <defs>
          <linearGradient id="login-time-gradient" x1="0" x2="0" y1="0" y2="1">
            <stop offset="0%" stopColor="rgba(16, 185, 129, 0.8)" />
            <stop offset="100%" stopColor="rgba(16, 185, 129, 0.1)" />
          </linearGradient>
        </defs>

        {points.length > 1 && (
          <polygon
            points={`${points
              .map((p) => `${p.x},${p.y}`)
              .join(" ")} ${points[points.length - 1].x},${height - padding} ${points[0].x},${height - padding}`}
            fill="url(#login-time-gradient)"
            opacity={0.35}
          />
        )}

        <line
          x1={padding}
          x2={width - padding}
          y1={height - padding}
          y2={height - padding}
          stroke="rgba(74, 222, 128, 0.3)"
          strokeWidth={0.8}
        />

        <polyline
          points={polyline}
          fill="none"
          stroke="rgba(16, 185, 129, 0.8)"
          strokeWidth={1.8}
          strokeLinecap="round"
          strokeLinejoin="round"
        />

        {points.map((p, idx) => (
          <circle
            key={`point-${idx}`}
            cx={p.x}
            cy={p.y}
            r={2.4}
            fill="rgba(45, 212, 191, 0.9)"
            stroke="rgba(8, 145, 178, 0.8)"
            strokeWidth={0.8}
          >
            <title>
              {`${dateFormatter.format(new Date(p.dateISO))} · ${(p.ms / 1000).toFixed(2)} s${
                valueSuffix ? ` ${valueSuffix}` : ""
              }`}
            </title>
          </circle>
        ))}
      </svg>

      <div className="mt-2 flex items-center justify-between text-[0.7rem] uppercase tracking-wide text-emerald-100/60">
        <span>
          {(minMs / 1000).toFixed(2)} s{valueSuffix ? ` ${valueSuffix}` : ""}
        </span>
        <span>
          Max {(maxMs / 1000).toFixed(2)} s{valueSuffix ? ` ${valueSuffix}` : ""}
        </span>
      </div>
      <div className="mt-1 flex flex-wrap gap-2 text-[0.65rem] font-mono text-emerald-100/50">
        {points.map((p, idx) => (
          <span key={`label-${idx}`}>{dateFormatter.format(new Date(p.dateISO))}</span>
        ))}
      </div>
    </div>
  );
}
