import React, { useMemo, useState } from "react";
import { motion } from "framer-motion";
import {
  Bar,
  BarChart,
  CartesianGrid,
  PolarAngleAxis,
  PolarGrid,
  PolarRadiusAxis,
  Radar,
  RadarChart,
  ResponsiveContainer,
  Tooltip,
  XAxis,
  YAxis,
} from "recharts";
import {
  CalendarDays,
  ClipboardCheck,
  Clock3,
  Eye,
  FileText,
  Gauge,
  KanbanSquare,
  Layers3,
  Plus,
  ShieldAlert,
  Sparkles,
  Target,
} from "lucide-react";
import { useSoc2Registry } from "./features/hooks/useSoc2Registry.js";
import { OFFICIAL_SCHEMA } from "./model/schema.js";
import { INITIAL_DB } from "./model/seed.js";
import { buildRegistryManifests, validateRegistry } from "./lib/validation.js";
import {
  buildBarData,
  buildBlockers,
  buildDataHealth,
  buildEvidenceMap,
  buildPackReadiness,
  buildRadarData,
  buildScoredPillars,
  computeGlobalScore,
  filterEvidence,
  getOverallStatus,
  getPackTone,
  getOwners,
} from "./lib/selectors.js";
import { daysUntil } from "./lib/utils.js";
import { PILLAR_ICONS } from "./lib/view.js";
import PillarOverviewCard from "./components/PillarOverviewCard.jsx";
import MilestoneCard from "./components/MilestoneCard.jsx";
import EvidenceLibrary from "./components/EvidenceLibrary.jsx";
import EvidenceEditor from "./components/EvidenceEditor.jsx";
import DataTab from "./components/DataTab.jsx";
import { ProgressBar, ScorePill, SectionTitle, Tag } from "./components/ui/primitives.jsx";

function DashboardPanel({ scoredPillars, targetReadiness, overall, selectedPillar, setSelectedPillar }) {
  const radarData = buildRadarData(scoredPillars, targetReadiness);

  return (
    <>
      <div className="grid dashboard-top gap-20">
        <div className="panel">
          <SectionTitle icon={Gauge} title="Radar de conformité" subtitle="Vue synthèse des 5 piliers. La cible interne est fixée à 85%." />
          <div className="chart-area">
            <ResponsiveContainer width="100%" height="100%">
              <RadarChart data={radarData} outerRadius="72%">
                <PolarGrid stroke="rgba(255,255,255,0.12)" />
                <PolarAngleAxis dataKey="subject" tick={{ fill: "#cbd5e1", fontSize: 13 }} />
                <PolarRadiusAxis domain={[0, 100]} tick={{ fill: "#64748b", fontSize: 11 }} />
                <Radar name="Cible" dataKey="target" stroke="#cbd5e1" fill="#cbd5e1" fillOpacity={0.07} />
                <Radar name="Actuel" dataKey="score" stroke="#60a5fa" fill="#60a5fa" fillOpacity={0.45} />
                <Tooltip />
              </RadarChart>
            </ResponsiveContainer>
          </div>
        </div>
        <div className="panel">
          <SectionTitle icon={Sparkles} title="Lecture utile du radar" subtitle="Le radar sert au pilotage. Il n’est pas une preuve à lui seul." />
          <div className="stack mt-16">
            <div className="subpanel"><div className="card-title-xs">Logique de score</div><div className="muted mt-8">Absent = 0, Conçu = 0,35, En opération = 0,7, Prouvé = 1. Les preuves bonifient la crédibilité du score.</div></div>
            <div className="subpanel"><div className="card-title-xs">Règle de plancher</div><div className="muted mt-8">Tant que Security reste sous 60%, l’état global doit être considéré fragile.</div></div>
            <div className={`subpanel ${overall.tone}`}><div className="card-title-xs">État actuel</div><div className="mt-8">{overall.label}</div></div>
          </div>
        </div>
      </div>
      <div className="grid pillars-grid gap-20 mt-20">
        {scoredPillars.map((pillar) => (
          <PillarOverviewCard key={pillar.id} pillar={pillar} selected={selectedPillar === pillar.id} onSelect={setSelectedPillar} />
        ))}
      </div>
    </>
  );
}

export default function App() {
  const registry = useSoc2Registry();
  const { db, lastSavedAt, importError, updateMilestoneStage, updateEvidence, toggleEvidenceMilestoneLink, createEvidence, deleteEvidence, exportDb, copyDb, importDb, resetDemo } = registry;

  const [activeTab, setActiveTab] = useState("dashboard");
  const [selectedPillar, setSelectedPillar] = useState("security");
  const [selectedEvidenceId, setSelectedEvidenceId] = useState(db.evidence[0]?.id || "");
  const [search, setSearch] = useState("");
  const [evidenceFilter, setEvidenceFilter] = useState("all");
  const [ownerFilter, setOwnerFilter] = useState("all");
  const [auditorMode, setAuditorMode] = useState(false);
  const [importText, setImportText] = useState("");

  const evidenceMap = useMemo(() => buildEvidenceMap(db), [db]);
  const scoredPillars = useMemo(() => buildScoredPillars(db, evidenceMap), [db, evidenceMap]);
  const selected = scoredPillars.find((pillar) => pillar.id === selectedPillar) || scoredPillars[0];
  const selectedEvidence = db.evidence.find((item) => item.id === selectedEvidenceId) || db.evidence[0] || null;
  const owners = useMemo(() => getOwners(db), [db]);
  const globalScore = useMemo(() => computeGlobalScore(db.pillars, evidenceMap), [db, evidenceMap]);
  const overall = getOverallStatus(globalScore);
  const auditWindowDays = daysUntil(db.appContext.observationWindow.end);
  const blockers = useMemo(() => buildBlockers(db, evidenceMap), [db, evidenceMap]);
  const packReadiness = useMemo(() => buildPackReadiness(db), [db]);
  const dataHealth = useMemo(() => buildDataHealth(db), [db]);
  const validation = useMemo(() => validateRegistry(db), [db]);
  const manifests = useMemo(() => buildRegistryManifests(db), [db]);

  const filteredEvidence = useMemo(
    () => filterEvidence(db, { query: search, pillarId: evidenceFilter, owner: ownerFilter, auditorMode }),
    [db, search, evidenceFilter, ownerFilter, auditorMode]
  );

  const barData = useMemo(() => buildBarData(selected, evidenceMap), [selected, evidenceMap]);
  const readyEvidenceCount = db.evidence.filter((item) => item.auditorReady).length;
  const readinessRate = db.evidence.length ? Math.round((readyEvidenceCount / db.evidence.length) * 1000) / 10 : 0;
  const blocker = scoredPillars.find((pillar) => pillar.id === "security" && pillar.score < 60);

  const handleCreateEvidence = () => {
    const id = createEvidence(selectedPillar);
    setSelectedEvidenceId(id);
    setActiveTab("evidence");
  };

  const handleDeleteEvidence = (evidenceId) => {
    deleteEvidence(evidenceId);
    const fallback = db.evidence.find((item) => item.id !== evidenceId);
    setSelectedEvidenceId(fallback?.id || "");
  };

  const handleImport = () => {
    const result = importDb(importText);
    if (result.ok) {
      setSelectedPillar(result.data.pillars[0]?.id || "security");
      setSelectedEvidenceId(result.data.evidence[0]?.id || "");
      setImportText("");
    }
  };

  const handleReset = () => {
    resetDemo();
    setSelectedPillar("security");
    setSelectedEvidenceId(INITIAL_DB.evidence[0]?.id || "");
  };

  return (
    <div className="app-shell">
      <div className="app-container">
        <motion.div initial={{ opacity: 0, y: 12 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.45 }} className="hero panel">
          <div className="grid hero-grid gap-20">
            <div>
              <div className="row wrap gap-8">
                <Tag tone="info">{db.appContext.orgName} • {db.appContext.programName}</Tag>
                <Tag tone={overall.tone}>{overall.label}</Tag>
                {blocker ? <Tag tone="is-bad">Blocage: Security &lt; 60</Tag> : null}
              </div>
              <h1 className="hero-title">Assistant web de conformité SOC 2 orienté preuve, remédiation et exposition auditeur</h1>
              <p className="hero-subtitle">Architecture modulaire, source de vérité versionnable, radar des 5 piliers, bibliothèque de preuves et salle auditeur.</p>
              <div className="row wrap gap-8 mt-16">
                <button className="btn btn-primary"><Eye size={16} /> Ouvrir la salle auditeur</button>
                <button className="btn btn-secondary" onClick={handleCreateEvidence}><Plus size={16} /> Nouvelle preuve</button>
                <button className="btn btn-secondary" onClick={() => setAuditorMode((v) => !v)}><ClipboardCheck size={16} /> {auditorMode ? "Mode interne" : "Mode auditeur"}</button>
              </div>
            </div>
            <div className="grid cols-2 gap-12">
              <ScorePill label="Conformité pondérée" value={`${globalScore}%`} sublabel="Score global des 5 piliers" />
              <ScorePill label="Preuves auditables" value={`${readinessRate}%`} sublabel={`${readyEvidenceCount}/${db.evidence.length} exposables aux auditeurs`} />
              <ScorePill label="Fenêtre Type II" value={`${auditWindowDays} j`} sublabel={`${db.appContext.observationWindow.start} → ${db.appContext.observationWindow.end}`} />
              <ScorePill label="Dernière sauvegarde" value={lastSavedAt || "—"} sublabel="Persistance locale automatique" />
            </div>
          </div>
        </motion.div>

        <div className="tabs panel mt-20">
          {["dashboard", "controls", "execution", "evidence", "auditor", "data"].map((tab) => (
            <button key={tab} className={`tab ${activeTab === tab ? "active" : ""}`} onClick={() => setActiveTab(tab)}>{tab}</button>
          ))}
        </div>

        {activeTab === "dashboard" && (
          <DashboardPanel scoredPillars={scoredPillars} targetReadiness={db.appContext.observationWindow.targetReadiness} overall={overall} selectedPillar={selectedPillar} setSelectedPillar={setSelectedPillar} />
        )}

        {activeTab === "controls" && (
          <div className="grid controls-grid gap-20">
            <div className="panel">
              <SectionTitle icon={PILLAR_ICONS[selected.id] || Layers3} title={`Pilier sélectionné : ${selected.name}`} subtitle={selected.objective} />
              <div className="grid cols-3 gap-12 mt-16">
                <ScorePill label="Score" value={`${selected.score}%`} sublabel="Maturité pondérée du pilier" />
                <ScorePill label="Poids global" value={`${selected.globalWeight}%`} sublabel="Charge relative dans l’ensemble" />
                <ScorePill label="Preuves" value={`${selected.evidenceCoverage}%`} sublabel="Couverture actuelle des éléments probants" />
              </div>
              <div className="chart-area chart-area-sm mt-16">
                <ResponsiveContainer width="100%" height="100%">
                  <BarChart data={barData} margin={{ top: 10, right: 10, left: -10, bottom: 40 }}>
                    <CartesianGrid strokeDasharray="3 3" stroke="rgba(255,255,255,0.08)" />
                    <XAxis dataKey="name" angle={-20} textAnchor="end" interval={0} height={80} tick={{ fill: "#cbd5e1", fontSize: 11 }} />
                    <YAxis domain={[0, 100]} tick={{ fill: "#94a3b8", fontSize: 11 }} />
                    <Tooltip />
                    <Bar dataKey="score" radius={[8, 8, 0, 0]} fill="#60a5fa" />
                  </BarChart>
                </ResponsiveContainer>
              </div>
            </div>
            <div className="panel panel-tall">
              <SectionTitle icon={KanbanSquare} title="Jalons détaillés" subtitle="Chaque jalon combine état d’implantation, cadence, propriétaire, échéance et chaîne de preuve." />
              <div className="scroll-area mt-16">
                <div className="stack">
                  {selected.milestones.map((milestone) => (
                    <MilestoneCard key={milestone.id} pillarId={selected.id} milestone={milestone} evidenceMap={evidenceMap} linkedEvidence={db.evidence.filter((item) => milestone.evidenceRefs.includes(item.id))} onStageChange={updateMilestoneStage} />
                  ))}
                </div>
              </div>
            </div>
          </div>
        )}

        {activeTab === "execution" && (
          <div className="grid execution-grid gap-20">
            <div className="panel">
              <SectionTitle icon={Target} title="Écarts et priorités" subtitle="Ce qui freine réellement la préparation Type II, trié par urgence et maturité." />
              <div className="stack mt-16">
                {blockers.map((item) => (
                  <div key={`${item.pillarId}-${item.id}`} className="subpanel">
                    <div className="row space-between align-start gap-12">
                      <div>
                        <div className="tiny muted">{item.pillarName}</div>
                        <div className="card-title-sm mt-6">{item.title}</div>
                      </div>
                      <Tag tone={item.dueInDays < 0 ? "is-bad" : item.dueInDays <= 7 ? "is-warn" : "is-muted"}>{item.dueInDays < 0 ? `Retard ${Math.abs(item.dueInDays)} j` : `${item.dueInDays} j`}</Tag>
                    </div>
                    <div className="muted mt-8">{item.nextAction}</div>
                  </div>
                ))}
              </div>
            </div>
            <div className="panel">
              <SectionTitle icon={CalendarDays} title="Cadence opérationnelle" subtitle="Vue synthèse du travail récurrent nécessaire pour faire vivre les contrôles et garder la preuve à jour." />
              <div className="grid cols-3 gap-12 mt-16">
                {db.pillars.flatMap((pillar) =>
                  pillar.milestones.map((milestone) => (
                    <div key={milestone.id} className="subpanel">
                      <div className="row space-between align-start gap-8"><Tag>{pillar.name}</Tag><Tag>{milestone.stage}</Tag></div>
                      <div className="card-title-sm mt-8">{milestone.title}</div>
                      <div className="muted mt-8">{milestone.owner} • {milestone.cadence}</div>
                      <div className="muted mt-8">Échéance: {milestone.dueAt}</div>
                    </div>
                  ))
                )}
              </div>
            </div>
          </div>
        )}

        {activeTab === "evidence" && (
          <div className="grid evidence-grid gap-20">
            <EvidenceLibrary
              evidence={filteredEvidence}
              selectedEvidenceId={selectedEvidenceId}
              onSelect={setSelectedEvidenceId}
              filters={{ search, setSearch, evidenceFilter, setEvidenceFilter, ownerFilter, setOwnerFilter }}
              owners={owners}
              pillars={db.pillars}
              onCreate={handleCreateEvidence}
            />
            <EvidenceEditor evidence={selectedEvidence} owners={owners} pillars={db.pillars} onUpdate={updateEvidence} onDelete={handleDeleteEvidence} onToggleLink={toggleEvidenceMilestoneLink} />
          </div>
        )}

        {activeTab === "auditor" && (
          <div className="grid auditor-grid gap-20">
            <div className="panel">
              <SectionTitle icon={FileText} title="Dossier auditeur" subtitle="Paquets structurés, lisibles, avec degré de préparation calculé." />
              <div className="stack mt-16">
                {packReadiness.map((pack) => (
                  <div key={pack.id} className="subpanel">
                    <div className="row space-between align-start gap-12"><div><div className="card-title-sm">{pack.title}</div><div className="muted mt-8">{pack.description}</div></div><Tag tone={getPackTone(pack.status)}>{pack.status}</Tag></div>
                    <div className="row space-between tiny muted mt-12"><span>Degré de préparation</span><span>{pack.readiness}%</span></div>
                    <ProgressBar value={pack.readiness} />
                    <div className="row wrap gap-8 mt-12">{pack.linked.map((item) => <Tag key={item.id}>{item.title}</Tag>)}</div>
                  </div>
                ))}
                <div className="subpanel is-info"><div className="row gap-8 align-center"><Clock3 size={16} /><strong>Mode {auditorMode ? "auditeur" : "interne"}</strong></div><div className="mt-8">{auditorMode ? "Affichage réduit aux preuves auditables." : "Affichage complet incluant brouillons et remédiation."}</div></div>
              </div>
            </div>
            <div className="panel">
              <SectionTitle icon={Layers3} title="Matériel exposé à l’auditeur" subtitle="Vue condensée du narratif d’audit : description du système, preuves, écarts connus et actions correctives." />
              <div className="stack mt-16">
                <div className="subpanel"><div className="card-title-xs">Description du système</div><div className="muted mt-8">Service in-scope, architecture, dépendances, responsabilités, flux de données, outils de surveillance, changements et posture de reprise.</div></div>
                <div className="subpanel"><div className="card-title-xs">Chaîne de preuve</div><div className="muted mt-8">Chaque jalon significatif doit être relié à des éléments probants datés, intelligibles et contextualisés, avec propriétaire et fraîcheur connue.</div></div>
                <div className="subpanel"><div className="card-title-xs">Écarts et remédiation</div><div className="muted mt-8">Les trous de conformité ne sont pas cachés. Ils sont nommés, qualifiés, suivis et accompagnés d’une action corrective explicite.</div></div>
                <div className="subpanel good"><div className="row gap-8 align-center"><ShieldAlert size={16} /><strong>Narratif recommandé</strong></div><div className="mt-8">Présenter d’abord le périmètre, puis les contrôles communs, ensuite les preuves les plus parlantes, et finir par les exceptions connues avec leurs remédiations.</div></div>
              </div>
            </div>
          </div>
        )}

        {activeTab === "data" && (
          <DataTab
            db={db}
            owners={owners}
            dataHealth={dataHealth}
            importText={importText}
            setImportText={setImportText}
            importError={importError}
            onImport={handleImport}
            onExport={exportDb}
            onCopy={copyDb}
            onReset={handleReset}
            validation={validation}
            manifests={manifests}
            schema={OFFICIAL_SCHEMA}
          />
        )}
      </div>
    </div>
  );
}
