import { useCallback, useEffect, useState } from 'react';
import { Loader2, FileText, Route, ListOrdered, Plus, Trash2, RefreshCw, Download } from 'lucide-react';
import { MarkdownRenderer } from '@/components/MarkdownRenderer';

interface ReportSummary {
  id: string;
  kind: string;
  interval: string;
  periodStart: string;
  periodEnd: string;
  createdAt: string;
}

interface ReportDetail extends ReportSummary {
  markdown: string;
  stats: Record<string, unknown> | null;
}

interface Policy {
  id: string;
  name: string;
  virtualModel: string;
  candidates: string[];
  fallback: string | null;
  enabled: boolean;
}

interface Dispatch {
  id: number;
  ts: string;
  virtualModel: string;
  chosenProviderId: string | null;
  chosenModel: string | null;
  candidatesTried: string[];
  status: string;
  source: string | null;
  error: string | null;
  durationMs: number | null;
}

type View = 'reports' | 'policies' | 'dispatch';

// D1: 'reports' tab shows digests; 'routing' tab shows policies + dispatch log.
// Default to all sub-views for backward compatibility.
export function ReportsTab({ mode = 'all' }: { mode?: 'reports' | 'routing' | 'all' }) {
  const subTabs: View[] = mode === 'reports' ? ['reports'] : mode === 'routing' ? ['policies', 'dispatch'] : ['reports', 'policies', 'dispatch'];
  const [view, setView] = useState<View>(subTabs[0]!);

  const LABEL: Record<View, { icon: typeof FileText; text: string }> = {
    reports: { icon: FileText, text: 'Reports' },
    policies: { icon: Route, text: 'Policies' },
    dispatch: { icon: ListOrdered, text: 'Dispatch Log' },
  };

  return (
    <div className="flex-1 flex flex-col min-h-0">
      {subTabs.length > 1 && (
        <div className="flex items-center gap-2 px-4 py-2 border-b border-border/40">
          {subTabs.map((t) => {
            const { icon: Icon, text } = LABEL[t];
            return (
              <button
                key={t}
                onClick={() => setView(t)}
                className={`px-3 py-1.5 text-xs rounded-md transition-colors ${view === t ? 'bg-primary/10 text-primary' : 'text-muted-foreground hover:text-foreground'}`}
              >
                <Icon className="size-3 inline mr-1" />
                {text}
              </button>
            );
          })}
        </div>
      )}

      <div className="flex-1 overflow-auto">
        {view === 'reports' && <ReportsView />}
        {view === 'policies' && <PoliciesView />}
        {view === 'dispatch' && <DispatchView />}
      </div>
    </div>
  );
}

function ReportsView() {
  const [reports, setReports] = useState<ReportSummary[]>([]);
  const [selected, setSelected] = useState<ReportDetail | null>(null);
  const [loading, setLoading] = useState(true);
  const [generating, setGenerating] = useState(false);
  const [schedule, setSchedule] = useState<{ interval: string; enabled: boolean; lastRunAt: string | null } | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const [rRes, sRes] = await Promise.all([
        fetch('/api/control/reports'),
        fetch('/api/control/reports/schedule'),
      ]);
      const rData = await rRes.json() as { reports: ReportSummary[] };
      setReports(rData.reports ?? []);
      setSchedule(await sRes.json());
    } catch (err) {
      console.error('reports: load failed', err);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { load(); }, [load]);

  const openReport = async (id: string) => {
    const res = await fetch(`/api/control/reports/${id}`);
    if (res.ok) setSelected(await res.json());
  };

  const generate = async () => {
    setGenerating(true);
    try {
      const res = await fetch('/api/control/reports/generate', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ interval: schedule?.interval ?? 'daily' }),
      });
      if (res.ok) {
        const { id } = await res.json() as { id: string };
        await load();
        await openReport(id);
      }
    } finally {
      setGenerating(false);
    }
  };

  const updateSchedule = async (patch: { interval?: string; enabled?: boolean }) => {
    const next = { interval: schedule?.interval ?? 'daily', enabled: schedule?.enabled ?? true, ...patch };
    await fetch('/api/control/reports/schedule', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(next),
    });
    setSchedule((prev) => prev ? { ...prev, ...patch } : prev);
  };

  const exportMarkdown = () => {
    if (!selected) return;
    const blob = new Blob([selected.markdown], { type: 'text/markdown' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${selected.id}.md`;
    a.click();
    URL.revokeObjectURL(url);
  };

  if (loading) {
    return <div className="flex items-center justify-center p-8"><Loader2 className="size-5 animate-spin text-muted-foreground" /></div>;
  }

  return (
    <div className="flex h-full min-h-0">
      {/* List + controls */}
      <div className="w-72 shrink-0 border-r border-border/40 flex flex-col min-h-0">
        <div className="p-3 border-b border-border/40 space-y-2">
          <button
            onClick={generate}
            disabled={generating}
            className="w-full flex items-center justify-center gap-1 px-3 py-1.5 text-xs bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50"
          >
            {generating ? <Loader2 className="size-3 animate-spin" /> : <RefreshCw className="size-3" />}
            Generate now
          </button>
          {schedule && (
            <div className="flex items-center gap-2 text-xs text-muted-foreground">
              <select
                value={schedule.interval}
                onChange={(e) => updateSchedule({ interval: e.target.value })}
                className="bg-background border border-border rounded px-1.5 py-0.5"
              >
                <option value="daily">Daily</option>
                <option value="weekly">Weekly</option>
              </select>
              <label className="flex items-center gap-1">
                <input
                  type="checkbox"
                  checked={schedule.enabled}
                  onChange={(e) => updateSchedule({ enabled: e.target.checked })}
                />
                scheduled
              </label>
            </div>
          )}
        </div>
        <div className="flex-1 overflow-auto">
          {reports.map((r) => (
            <button
              key={r.id}
              onClick={() => openReport(r.id)}
              className={`w-full text-left px-3 py-2 text-xs border-b border-border/20 hover:bg-muted/20 ${selected?.id === r.id ? 'bg-muted/30' : ''}`}
            >
              <div className="font-medium capitalize">{r.interval} digest</div>
              <div className="text-muted-foreground">{new Date(r.createdAt).toLocaleString()}</div>
            </button>
          ))}
          {reports.length === 0 && (
            <div className="p-4 text-center text-xs text-muted-foreground">No reports yet. Generate one.</div>
          )}
        </div>
      </div>

      {/* Detail */}
      <div className="flex-1 overflow-auto p-4 min-w-0">
        {selected ? (
          <>
            <div className="flex items-center justify-between mb-3">
              <h2 className="text-sm font-medium">{selected.interval} digest</h2>
              <button
                onClick={exportMarkdown}
                className="flex items-center gap-1 px-2 py-1 text-xs border border-border rounded-md hover:bg-muted/30"
              >
                <Download className="size-3" /> Export .md
              </button>
            </div>
            <div className="prose-sm max-w-none">
              <MarkdownRenderer content={selected.markdown} />
            </div>
          </>
        ) : (
          <div className="flex items-center justify-center h-full text-sm text-muted-foreground">
            Select a report to view it.
          </div>
        )}
      </div>
    </div>
  );
}

function PoliciesView() {
  const [policies, setPolicies] = useState<Policy[]>([]);
  const [virtualModels, setVirtualModels] = useState<string[]>([]);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState<Partial<Policy> | null>(null);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const [pRes, vRes] = await Promise.all([
        fetch('/api/control/policies'),
        fetch('/api/control/policies/virtual-models'),
      ]);
      const pData = await pRes.json() as { policies: Policy[] };
      const vData = await vRes.json() as { virtualModels: string[] };
      setPolicies(pData.policies ?? []);
      setVirtualModels(vData.virtualModels ?? []);
    } catch (err) {
      console.error('policies: load failed', err);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { load(); }, [load]);

  const save = async () => {
    if (!editing?.name || !editing?.virtualModel) return;
    await fetch('/api/control/policies', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        name: editing.name,
        virtualModel: editing.virtualModel,
        candidates: editing.candidates ?? [],
        fallback: editing.fallback ?? null,
        enabled: editing.enabled !== false,
      }),
    });
    setEditing(null);
    await load();
  };

  const remove = async (id: string) => {
    await fetch(`/api/control/policies/${id}`, { method: 'DELETE' });
    await load();
  };

  if (loading) {
    return <div className="flex items-center justify-center p-8"><Loader2 className="size-5 animate-spin text-muted-foreground" /></div>;
  }

  return (
    <div className="p-4 space-y-4">
      <div className="flex items-center justify-between">
        <p className="text-xs text-muted-foreground">
          Route policies order candidate models for each <code>auto:*</code> virtual model. Candidates are composite ids (<code>provider/model</code>). Unset policies fall back to advisory scores.
        </p>
        <button
          onClick={() => setEditing({ enabled: true, candidates: [] })}
          className="flex items-center gap-1 px-3 py-1.5 text-xs bg-primary text-primary-foreground rounded-md hover:bg-primary/90 shrink-0"
        >
          <Plus className="size-3" /> New policy
        </button>
      </div>

      {editing && (
        <div className="border border-border/40 rounded-lg p-3 bg-card/30 space-y-2">
          <input
            placeholder="Policy name"
            value={editing.name ?? ''}
            onChange={(e) => setEditing({ ...editing, name: e.target.value })}
            className="w-full text-xs bg-background border border-border rounded-md px-2 py-1"
          />
          <select
            value={editing.virtualModel ?? ''}
            onChange={(e) => setEditing({ ...editing, virtualModel: e.target.value })}
            className="w-full text-xs bg-background border border-border rounded-md px-2 py-1"
          >
            <option value="">Select virtual model…</option>
            {virtualModels.map((v) => <option key={v} value={v}>{v}</option>)}
          </select>
          <textarea
            placeholder="Candidates, one composite id per line (e.g. sam-desktop/qwopus-35b)"
            value={(editing.candidates ?? []).join('\n')}
            onChange={(e) => setEditing({ ...editing, candidates: e.target.value.split('\n').map((s) => s.trim()).filter(Boolean) })}
            className="w-full text-xs font-mono bg-background border border-border rounded-md px-2 py-1 h-24"
          />
          <input
            placeholder="Fallback composite id (optional)"
            value={editing.fallback ?? ''}
            onChange={(e) => setEditing({ ...editing, fallback: e.target.value })}
            className="w-full text-xs font-mono bg-background border border-border rounded-md px-2 py-1"
          />
          <div className="flex items-center gap-2">
            <button onClick={save} className="px-3 py-1 text-xs bg-primary text-primary-foreground rounded-md hover:bg-primary/90">Save</button>
            <button onClick={() => setEditing(null)} className="px-3 py-1 text-xs border border-border rounded-md hover:bg-muted/30">Cancel</button>
          </div>
        </div>
      )}

      <div className="space-y-2">
        {policies.map((p) => (
          <div key={p.id} className="border border-border/40 rounded-lg p-3 bg-card/50">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-2">
                <span className="text-sm font-medium">{p.name}</span>
                <code className="text-xs px-1.5 py-0.5 bg-muted/40 rounded">{p.virtualModel}</code>
                {!p.enabled && <span className="text-xs text-muted-foreground">(disabled)</span>}
              </div>
              <div className="flex items-center gap-1">
                <button onClick={() => setEditing(p)} className="px-2 py-0.5 text-xs border border-border rounded hover:bg-muted/30">Edit</button>
                <button onClick={() => remove(p.id)} className="p-1 text-muted-foreground hover:text-red-400"><Trash2 className="size-3" /></button>
              </div>
            </div>
            <ol className="mt-2 text-xs font-mono text-muted-foreground list-decimal list-inside">
              {p.candidates.map((c) => <li key={c}>{c}</li>)}
              {p.fallback && <li className="text-amber-400">{p.fallback} (fallback)</li>}
            </ol>
          </div>
        ))}
        {policies.length === 0 && !editing && (
          <div className="p-4 text-center text-xs text-muted-foreground">No policies. The gateway uses advisory scores until one is added.</div>
        )}
      </div>
    </div>
  );
}

function DispatchView() {
  const [dispatches, setDispatches] = useState<Dispatch[]>([]);
  const [loading, setLoading] = useState(true);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const res = await fetch('/api/control/policies/dispatch-log');
      const data = await res.json() as { dispatches: Dispatch[] };
      setDispatches(data.dispatches ?? []);
    } catch (err) {
      console.error('dispatch-log: load failed', err);
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => { load(); }, [load]);

  if (loading) {
    return <div className="flex items-center justify-center p-8"><Loader2 className="size-5 animate-spin text-muted-foreground" /></div>;
  }

  return (
    <div className="p-4">
      <div className="flex items-center justify-between mb-2">
        <h3 className="text-sm font-medium">Gateway dispatches</h3>
        <button onClick={load} className="flex items-center gap-1 px-2 py-1 text-xs border border-border rounded-md hover:bg-muted/30">
          <RefreshCw className="size-3" /> Refresh
        </button>
      </div>
      <div className="overflow-x-auto">
        <table className="w-full text-xs">
          <thead>
            <tr className="border-b border-border/40 text-muted-foreground">
              <th className="text-left py-2 px-3">Time</th>
              <th className="text-left py-2 px-3">Virtual</th>
              <th className="text-left py-2 px-3">Chosen</th>
              <th className="text-left py-2 px-3">Status</th>
              <th className="text-left py-2 px-3">Source</th>
              <th className="text-left py-2 px-3">ms</th>
              <th className="text-left py-2 px-3">Tried</th>
            </tr>
          </thead>
          <tbody>
            {dispatches.map((d) => (
              <tr key={d.id} className="border-b border-border/20 hover:bg-muted/20">
                <td className="py-2 px-3 text-muted-foreground">{new Date(d.ts).toLocaleTimeString()}</td>
                <td className="py-2 px-3 font-mono">{d.virtualModel}</td>
                <td className="py-2 px-3 font-mono">{d.chosenProviderId ? `${d.chosenProviderId}/${d.chosenModel}` : '-'}</td>
                <td className="py-2 px-3">
                  <span className={`px-2 py-0.5 rounded-full ${
                    d.status === 'dispatched' ? 'bg-green-500/20 text-green-400' :
                    d.status === 'failed' || d.status === 'no_candidates' ? 'bg-red-500/20 text-red-400' :
                    'bg-yellow-500/20 text-yellow-400'
                  }`}>{d.status}</span>
                </td>
                <td className="py-2 px-3 text-muted-foreground">{d.source ?? '-'}</td>
                <td className="py-2 px-3 font-mono">{d.durationMs ?? '-'}</td>
                <td className="py-2 px-3 font-mono text-muted-foreground">{d.candidatesTried.length}</td>
              </tr>
            ))}
            {dispatches.length === 0 && (
              <tr><td colSpan={7} className="py-8 text-center text-muted-foreground">No gateway dispatches yet.</td></tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}
