import { useState, useEffect } from 'react';
import { Gauge, FlaskConical, Loader2, AlertTriangle, Sparkles, ShieldAlert, ShieldCheck } from 'lucide-react';
import { Card } from './ui/card';
import { Button } from './ui/button';
import { API_BASE_URL } from '../config';

interface ClassStats {
  precision: number;
  recall: number;
  f1: number;
  support: number;
}

interface Metrics {
  modelName: string;
  datasetSize: number;
  numClasses: number;
  testSize: number;
  testFraction: number;
  trainGroupCount: number;
  testGroupCount: number;
  groupOverlap: number;
  splitMethod: string;
  accuracy: number;
  macroF1: number;
  weightedF1: number;
  logLoss: number;
  calibrated: boolean;
  calibrationMethod: string;
  perClass: Record<string, ClassStats>;
  classDistribution: Record<string, number>;
  rareClasses: Record<string, number>;
  minimumRecommendedClassSize: number;
  confusionMatrix: { labels: string[]; matrix: number[][] };
}

interface TextResult {
  text: string;
  prediction: string;
  confidence: number;
  isDarkPattern: boolean;
  topClasses: { label: string; probability: number }[];
  explanation: { phrase: string; weight: number }[];
  calibrated: boolean;
  confidenceBand: string;
  cfpbViolation?: string;
  recommendation?: string;
}

const EXAMPLE_TEXTS = [
  'Hurry! Only 3 left in stock — sale ends in 10 minutes!',
  '2,847 customers bought this in the last 24 hours',
  'No thanks, I hate saving money',
  'Your monthly statement is available in the documents section.',
];

export function ModelPerformance() {
  const [metrics, setMetrics] = useState<Metrics | null>(null);
  const [metricsError, setMetricsError] = useState<string | null>(null);
  const [text, setText] = useState('');
  const [testing, setTesting] = useState(false);
  const [result, setResult] = useState<TextResult | null>(null);
  const [testError, setTestError] = useState<string | null>(null);

  useEffect(() => {
    fetch(`${API_BASE_URL}/api/metrics`)
      .then((r) => {
        if (!r.ok) throw new Error(`Server returned ${r.status}`);
        return r.json();
      })
      .then(setMetrics)
      .catch((e) => setMetricsError(e.message));
  }, []);

  const runTest = async (input?: string) => {
    const value = (input ?? text).trim();
    if (value.length < 3) return;
    if (input) setText(input);
    setTesting(true);
    setTestError(null);
    setResult(null);
    try {
      const r = await fetch(`${API_BASE_URL}/api/analyze-text`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ text: value }),
      });
      const data = await r.json();
      if (!r.ok || data.error) throw new Error(data.error || `Server returned ${r.status}`);
      setResult(data);
    } catch (e: any) {
      setTestError(e.message);
    } finally {
      setTesting(false);
    }
  };

  const f1Color = (f1: number) =>
    f1 >= 0.9 ? 'bg-emerald-500' : f1 >= 0.7 ? 'bg-amber-500' : 'bg-rose-500';

  return (
    <div className="space-y-8">
      {/* ── Live Text Lab ─────────────────────────────────────────── */}
      <Card className="p-8 bg-card/40 backdrop-blur-md border border-border shadow-xl rounded-2xl">
        <h2 className="text-xl font-bold text-foreground mb-1 flex items-center gap-2">
          <FlaskConical className="w-5 h-5 text-indigo-500 dark:text-indigo-400" />
          Live Text Lab
        </h2>
        <p className="text-xs text-muted-foreground mb-6">
          Paste any fintech copywriting and see what the model thinks — and which phrases drove the decision.
        </p>

        <div className="flex flex-col md:flex-row gap-3">
          <input
            value={text}
            onChange={(e) => setText(e.target.value)}
            onKeyDown={(e) => e.key === 'Enter' && runTest()}
            placeholder='e.g. "Hurry! Only 2 left in stock!"'
            className="flex-1 px-4 py-3 rounded-xl bg-muted/20 border border-border text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-indigo-500/60"
          />
          <Button
            onClick={() => runTest()}
            disabled={testing || text.trim().length < 3}
            className="h-12 px-8 rounded-xl text-xs font-bold uppercase tracking-wider bg-gradient-to-r from-indigo-600 to-purple-600 hover:from-indigo-500 hover:to-purple-500 text-white"
          >
            {testing ? <Loader2 className="w-4 h-4 animate-spin" /> : 'Classify'}
          </Button>
        </div>

        <div className="flex flex-wrap gap-2 mt-3">
          {EXAMPLE_TEXTS.map((t) => (
            <button
              key={t}
              onClick={() => runTest(t)}
              className="text-[11px] px-3 py-1.5 rounded-full border border-border bg-muted/10 text-muted-foreground hover:text-foreground hover:border-indigo-500/40 transition-colors"
            >
              {t}
            </button>
          ))}
        </div>

        {testError && (
          <div className="mt-4 p-3 rounded-xl text-rose-500 bg-rose-500/10 border border-rose-500/25 text-xs font-semibold">
            {testError}
          </div>
        )}

        {result && (
          <div className="mt-6 p-5 rounded-xl border border-border bg-muted/10 space-y-4">
            <div className="flex items-center gap-3 flex-wrap">
              {result.isDarkPattern ? (
                <ShieldAlert className="w-6 h-6 text-rose-500" />
              ) : (
                <ShieldCheck className="w-6 h-6 text-emerald-500" />
              )}
              <span
                className={`text-sm font-extrabold uppercase tracking-wide ${
                  result.isDarkPattern ? 'text-rose-500' : 'text-emerald-500'
                }`}
              >
                {result.prediction}
              </span>
              <span className="text-xs font-mono text-muted-foreground">
                {result.confidence}% calibrated confidence ({result.confidenceBand})
              </span>
            </div>

            {result.explanation.length > 0 && (
              <div>
                <div className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground mb-2 flex items-center gap-1.5">
                  <Sparkles className="w-3 h-3" /> Phrases that triggered this verdict
                </div>
                <div className="flex flex-wrap gap-2">
                  {result.explanation.map((e) => (
                    <span
                      key={e.phrase}
                      className="text-xs font-mono px-2.5 py-1 rounded-md bg-indigo-500/10 text-indigo-500 dark:text-indigo-300 border border-indigo-500/25"
                      title={`weight ${e.weight}`}
                    >
                      {e.phrase}
                    </span>
                  ))}
                </div>
              </div>
            )}

            <div className="grid grid-cols-3 gap-2">
              {result.topClasses.map((c) => (
                <div key={c.label} className="p-2.5 rounded-lg bg-muted/20 border border-border">
                  <div className="text-[10px] text-muted-foreground truncate">{c.label}</div>
                  <div className="text-sm font-bold text-foreground">{c.probability}%</div>
                </div>
              ))}
            </div>

            {result.cfpbViolation && (
              <div className="p-3 rounded-lg bg-amber-500/10 border border-amber-500/25 text-xs text-amber-600 dark:text-amber-400">
                <strong>Compliance:</strong> {result.cfpbViolation}
              </div>
            )}
          </div>
        )}
      </Card>

      {/* ── Evaluation metrics ────────────────────────────────────── */}
      <Card className="p-8 bg-card/40 backdrop-blur-md border border-border shadow-xl rounded-2xl">
        <h2 className="text-xl font-bold text-foreground mb-1 flex items-center gap-2">
          <Gauge className="w-5 h-5 text-indigo-500 dark:text-indigo-400" />
          Model Performance
        </h2>
        <p className="text-xs text-muted-foreground mb-6">
          Evaluated on a grouped held-out fold. Text from the same source page never appears in both training and testing.
        </p>

        {metricsError && (
          <div className="p-4 rounded-xl text-rose-500 bg-rose-500/10 border border-rose-500/25 text-xs font-semibold">
            Failed to load metrics: {metricsError}
          </div>
        )}

        {!metrics && !metricsError && (
          <div className="flex items-center justify-center py-16">
            <Loader2 className="w-6 h-6 animate-spin text-indigo-500" />
          </div>
        )}

        {metrics && (
          <div className="space-y-8">
            <div className="text-xs font-mono text-muted-foreground">{metrics.modelName}</div>
            <div className="text-[11px] text-muted-foreground">
              {metrics.splitMethod} · {metrics.testGroupCount} test pages · {metrics.groupOverlap} page overlap · {metrics.calibrationMethod}
            </div>

            <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
              {[
                { label: 'Accuracy', value: `${(metrics.accuracy * 100).toFixed(1)}%` },
                { label: 'Macro F1', value: metrics.macroF1.toFixed(3) },
                { label: 'Weighted F1', value: metrics.weightedF1.toFixed(3) },
                { label: 'Training samples', value: metrics.datasetSize.toLocaleString() },
              ].map((s) => (
                <div key={s.label} className="p-4 rounded-xl bg-muted/10 border border-border">
                  <div className="text-[10px] font-bold uppercase tracking-widest text-muted-foreground">
                    {s.label}
                  </div>
                  <div className="text-2xl font-extrabold text-foreground mt-1">{s.value}</div>
                </div>
              ))}
            </div>

            {/* Per-class table */}
            <div>
              <h3 className="text-sm font-bold text-foreground mb-3">F1 score per pattern class</h3>
              <div className="space-y-2">
                {Object.entries(metrics.perClass)
                  .sort((a, b) => b[1].f1 - a[1].f1)
                  .map(([cls, s]) => (
                    <div key={cls} className="flex items-center gap-3">
                      <div className="w-36 text-xs font-semibold text-foreground truncate">{cls}</div>
                      <div className="flex-1 h-3 rounded-full bg-muted/30 overflow-hidden">
                        <div
                          className={`h-full rounded-full ${f1Color(s.f1)}`}
                          style={{ width: `${Math.max(s.f1 * 100, 2)}%` }}
                        />
                      </div>
                      <div className="w-12 text-xs font-mono text-foreground text-right">
                        {s.f1.toFixed(2)}
                      </div>
                      <div className="w-20 text-[10px] font-mono text-muted-foreground text-right">
                        n={s.support}
                      </div>
                    </div>
                  ))}
              </div>
            </div>

            {/* Low-support warning — honest about dataset limitations */}
            {Object.keys(metrics.rareClasses).length > 0 && (
              <div className="flex items-start gap-2.5 p-3.5 rounded-xl bg-amber-500/10 border border-amber-500/25">
                <AlertTriangle className="w-4 h-4 text-amber-500 mt-0.5 shrink-0" />
                <p className="text-xs text-amber-600 dark:text-amber-400 leading-relaxed">
                  Classes below {metrics.minimumRecommendedClassSize} total samples remain unreliable:{' '}
                  {Object.entries(metrics.rareClasses)
                    .map(([label, count]) => `${label} (${count})`)
                    .join(', ')}. No synthetic records were added to inflate these scores.
                </p>
              </div>
            )}

            {/* Confusion matrix */}
            <div>
              <h3 className="text-sm font-bold text-foreground mb-3">Confusion matrix (rows = truth, columns = prediction)</h3>
              <div className="overflow-x-auto">
                <table className="text-[10px] font-mono border-collapse">
                  <thead>
                    <tr>
                      <th className="p-1.5" />
                      {metrics.confusionMatrix.labels.map((l) => (
                        <th key={l} className="p-1.5 text-muted-foreground font-semibold max-w-16 truncate" title={l}>
                          {l.split(' ')[0]}
                        </th>
                      ))}
                    </tr>
                  </thead>
                  <tbody>
                    {metrics.confusionMatrix.matrix.map((row, i) => {
                      const rowMax = Math.max(...row, 1);
                      return (
                        <tr key={metrics.confusionMatrix.labels[i]}>
                          <td className="p-1.5 text-muted-foreground font-semibold text-right pr-3 whitespace-nowrap">
                            {metrics.confusionMatrix.labels[i]}
                          </td>
                          {row.map((v, j) => (
                            <td
                              key={j}
                              className={`p-1.5 text-center min-w-12 rounded ${
                                v === 0
                                  ? 'text-muted-foreground/40'
                                  : i === j
                                    ? 'text-emerald-500 font-bold'
                                    : 'text-rose-500 font-bold'
                              }`}
                              style={{
                                backgroundColor:
                                  v > 0
                                    ? i === j
                                      ? `rgba(16,185,129,${0.08 + 0.3 * (v / rowMax)})`
                                      : `rgba(244,63,94,${0.08 + 0.3 * (v / rowMax)})`
                                    : undefined,
                              }}
                            >
                              {v}
                            </td>
                          ))}
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            </div>
          </div>
        )}
      </Card>
    </div>
  );
}
