import { useQuery } from '@tanstack/react-query';
import { auditLogApi, IntegrityResult } from '../../services/api';
import Card from '../../components/ui/Card';
import Button from '../../components/ui/Button';
import {
  ShieldCheck, ShieldAlert, ShieldQuestion, RefreshCw, Loader2, ChevronDown, ChevronUp,
} from 'lucide-react';
import { useState } from 'react';

/**
 * Statuskarte fuer die Unversehrtheit des Audit-Protokolls.
 *
 * Die Prueflast steigt mit der Groesse des Protokolls (die Pruefung liest die
 * gesamte Kette). Deshalb laeuft sie beim Oeffnen der Seite EINMAL und wird
 * fuenf Minuten lang wiederverwendet; wer sofort neu pruefen will, nutzt den
 * Knopf.
 */

type Ampel = 'ok' | 'befund' | 'hinweis' | 'unbekannt';

function ampelFuer(r: IntegrityResult): Ampel {
  if (!r.valid) return 'befund';
  // Gueltig, aber nicht vollstaendig pruefbar: kein gruenes Licht vortaeuschen.
  if (r.unverifiableEntries.length > 0) return 'unbekannt';
  if (r.backlogSealStatus === 'kein_siegel') return 'hinweis';
  return 'ok';
}

const AMPEL_STIL: Record<Ampel, { box: string; titel: string; text: string }> = {
  ok:        { box: 'bg-green-50 border-green-200',  titel: 'text-green-900',  text: 'text-green-800' },
  befund:    { box: 'bg-red-50 border-red-200',      titel: 'text-red-900',    text: 'text-red-800' },
  hinweis:   { box: 'bg-yellow-50 border-yellow-200',titel: 'text-yellow-900', text: 'text-yellow-800' },
  unbekannt: { box: 'bg-gray-50 border-gray-200',    titel: 'text-gray-900',   text: 'text-gray-700' },
};

function AmpelIcon({ ampel }: { ampel: Ampel }) {
  const c = 'w-7 h-7 shrink-0';
  if (ampel === 'ok') return <ShieldCheck className={`${c} text-green-600`} />;
  if (ampel === 'befund') return <ShieldAlert className={`${c} text-red-600`} />;
  if (ampel === 'hinweis') return <ShieldAlert className={`${c} text-yellow-600`} />;
  return <ShieldQuestion className={`${c} text-gray-500`} />;
}

const AMPEL_TITEL: Record<Ampel, string> = {
  ok: 'Protokoll unversehrt',
  befund: 'Befund – das gehört angesehen',
  hinweis: 'Unversehrt, aber ungeschützter Altbestand',
  unbekannt: 'Nicht vollständig prüfbar',
};

const SIEGEL_TEXT: Record<IntegrityResult['backlogSealStatus'], string> = {
  intakt: 'versiegelt und intakt',
  leer: 'Siegel vorhanden, aber ohne Inhalt',
  kein_siegel: 'nicht versiegelt',
  nicht_noetig: 'nicht nötig (alles signiert)',
  gebrochen: 'GEBROCHEN',
  entfernt: 'ENTFERNT',
};

/** Zeigt eine Zahl nur, wenn sie ungleich null ist – sonst bleibt es ruhig. */
function Zahl({ label, ids, ton }: { label: string; ids: number[]; ton: string }) {
  if (ids.length === 0) return null;
  const gekuerzt = ids.length > 12 ? `${ids.slice(0, 12).join(', ')} … (+${ids.length - 12})` : ids.join(', ');
  return (
    <div className="flex items-baseline gap-2 text-sm">
      <span className={`font-medium ${ton}`}>{label}:</span>
      <span className="text-gray-600">{ids.length}</span>
      <span className="text-gray-400 font-mono text-xs break-all">({gekuerzt})</span>
    </div>
  );
}

export default function AuditIntegrityCard() {
  const [offen, setOffen] = useState(false);
  const { data, isFetching, isError, error, refetch } = useQuery({
    queryKey: ['audit-integrity'],
    queryFn: () => auditLogApi.verifyIntegrity(),
    staleTime: 5 * 60 * 1000,
    refetchOnWindowFocus: false,
    retry: false,
  });

  const ergebnis = data?.data;

  return (
    <Card
      className="mb-6"
      title="Unversehrtheit des Protokolls"
      actions={
        <Button variant="secondary" onClick={() => refetch()} disabled={isFetching}>
          {isFetching
            ? <Loader2 className="w-4 h-4 mr-2 animate-spin" />
            : <RefreshCw className="w-4 h-4 mr-2" />}
          Neu prüfen
        </Button>
      }
    >
      {isFetching && !ergebnis && (
        <div className="flex items-center gap-3 text-gray-500">
          <Loader2 className="w-5 h-5 animate-spin" />
          <span>Die Kette wird geprüft …</span>
        </div>
      )}

      {isError && (
        <div className="flex items-start gap-4 p-4 rounded-lg border bg-gray-50 border-gray-200">
          <ShieldQuestion className="w-7 h-7 shrink-0 text-gray-500" />
          <div>
            <p className="font-medium text-gray-900">Prüfung nicht möglich</p>
            <p className="text-sm text-gray-700 mt-1">
              {error instanceof Error ? error.message : 'Unbekannter Fehler'}
            </p>
            <p className="text-sm text-gray-600 mt-2">
              Das ist <strong>keine</strong> Entwarnung – der Zustand der Kette ist damit
              schlicht unbekannt.
            </p>
          </div>
        </div>
      )}

      {ergebnis && (() => {
        const ampel = ampelFuer(ergebnis);
        const stil = AMPEL_STIL[ampel];
        return (
          <>
            <div className={`flex items-start gap-4 p-4 rounded-lg border ${stil.box}`}>
              <AmpelIcon ampel={ampel} />
              <div className="min-w-0">
                <p className={`font-medium ${stil.titel}`}>
                  {AMPEL_TITEL[ampel]}
                  {ampel === 'ok' && ergebnis.rehashes.length > 0 && (
                    <span className="font-normal"> – seit der letzten Neuberechnung</span>
                  )}
                </p>
                <p className={`text-sm mt-1 ${stil.text}`}>{ergebnis.message}</p>
                <p className="text-sm text-gray-500 mt-2">
                  {ergebnis.checkedCount.toLocaleString('de-DE')} Einträge geprüft ·
                  {' '}Altbestand: {SIEGEL_TEXT[ergebnis.backlogSealStatus]}
                  {ergebnis.backlogSealCount > 1 && ` · ${ergebnis.backlogSealCount}× versiegelt`}
                </p>
              </div>
            </div>

            <button
              type="button"
              onClick={() => setOffen(o => !o)}
              className="mt-3 flex items-center gap-1 text-sm text-gray-600 hover:text-gray-900"
            >
              {offen ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
              Einzelheiten
            </button>

            {offen && (
              <div className="mt-3 space-y-2 border-t pt-3">
                <Zahl label="Nachträglich verändert" ids={ergebnis.tamperedEntries} ton="text-red-700" />
                <Zahl label="Gesiegelte Alteinträge verändert" ids={ergebnis.backlogTampered} ton="text-red-700" />
                <Zahl label="Gesiegelte Alteinträge entfernt" ids={ergebnis.backlogMissing} ton="text-red-700" />
                <Zahl label="Verkettung unterbrochen" ids={ergebnis.chainGaps} ton="text-yellow-700" />
                <Zahl label="davon ohne dokumentierte Löschung" ids={ergebnis.unexplainedGaps} ton="text-yellow-700" />
                <Zahl label="davon vom Siegel beglaubigt" ids={ergebnis.attestedGaps} ton="text-gray-700" />
                <Zahl label="Ohne Schlüssel nicht prüfbar" ids={ergebnis.unverifiableEntries} ton="text-gray-700" />
                {ergebnis.tamperedEntries.length === 0 &&
                  ergebnis.chainGaps.length === 0 &&
                  ergebnis.unverifiableEntries.length === 0 &&
                  ergebnis.rehashes.length === 0 && (
                    <p className="text-sm text-gray-500 italic">Nichts zu berichten.</p>
                  )}
                {ergebnis.rehashes.length > 0 && (
                  <div className="pt-2 border-t mt-2">
                    <p className="text-sm font-medium text-gray-700">Neuberechnungen der Kette</p>
                    {ergebnis.rehashes.map((r) => (
                      <p key={r.id} className="text-sm text-gray-600 mt-1">
                        {new Date(r.zeitpunkt).toLocaleString('de-DE')} · Eintrag {r.id}
                        {r.neuBerechnet !== null && ` · ${r.neuBerechnet} Einträge neu verkettet`}
                        {r.vorbefund && (
                          <span className="text-gray-500">
                            {' '}· davor: {r.vorbefund.manipuliert} beanstandet,{' '}
                            {r.vorbefund.luecken} Lücken
                          </span>
                        )}
                        {!r.signiert && (
                          <span className="text-red-700"> · ohne gültige Signatur</span>
                        )}
                      </p>
                    ))}
                    <p className="text-xs text-gray-500 mt-2">
                      Ein Rehash verknüpft alle Einträge neu. Was davor als Lücke oder
                      Beanstandung sichtbar war, ist danach nicht mehr in der Kette zu sehen –
                      nur noch im Vorbefund des jeweiligen Eintrags. Die Aussage dieser Prüfung
                      reicht deshalb bis zur letzten Neuberechnung zurück, nicht weiter.
                    </p>
                  </div>
                )}
                <p className="text-xs text-gray-500 pt-2">
                  <strong>Verändert</strong> heißt: der Inhalt einer bestehenden Zeile passt nicht
                  mehr zu ihrer Prüfsumme – das ist ernst.
                  {' '}<strong>Verkettung unterbrochen</strong> heißt: die Zeilen selbst sind
                  unversehrt, aber ein Glied fehlt oder wurde parallel geschrieben.
                  {' '}<strong>Beglaubigt</strong> sind Lücken, die beim Versiegeln des Altbestands
                  bereits bestanden und im signierten Siegel festgehalten sind.
                </p>
              </div>
            )}
          </>
        );
      })()}
    </Card>
  );
}
