'use client';

import { useCallback, useEffect, useState } from 'react';
import { isAxiosError } from 'axios';
import { Loader2 } from 'lucide-react';

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import {
  extractApiErrorMessage,
  fetchJournal,
  type JournalEntree,
  type Piece,
} from '@/lib/api';
import { formatDateJournal, libelleFonction } from '@/lib/journal';
import { cn } from '@/lib/utils';

type PieceJournalDialogProps = {
  piece: Piece | null;
  onOpenChange: (open: boolean) => void;
};

function formatBytes(bytes: number | null): string {
  if (bytes === null) {
    return '—';
  }

  if (bytes < 1024) {
    return `${bytes} o`;
  }

  if (bytes < 1024 * 1024) {
    return `${Math.round(bytes / 1024)} Ko`;
  }

  return `${(bytes / (1024 * 1024)).toFixed(1)} Mo`;
}

/**
 * Fonction Lire Journal (§5.2.6) appelée avec le seul paramètre IDU, donc
 * exclusif de tout filtre de date ou d'ID_ON_UTI : tous les enregistrements
 * du journal du CCFN associés à cet ON, y compris s'il a été détruit (§5.1.1).
 */
export function PieceJournalDialog({
  piece,
  onOpenChange,
}: PieceJournalDialogProps) {
  const [entrees, setEntrees] = useState<JournalEntree[]>([]);
  const [isLoading, setIsLoading] = useState(false);
  const [loadError, setLoadError] = useState<string | null>(null);

  const idu = piece?.idu ?? null;

  const charger = useCallback(async (identifiant: string) => {
    setIsLoading(true);
    setLoadError(null);
    setEntrees([]);

    try {
      const lecture = await fetchJournal({ idu: identifiant });
      setEntrees(lecture.entrees);
    } catch (error) {
      if (isAxiosError(error) && error.response?.status === 403) {
        setLoadError(
          'Votre profil ne permet pas de lire le journal (fonction « Lire journal » requise).',
        );
      } else {
        setLoadError(
          extractApiErrorMessage(error, 'Impossible de lire le journal.'),
        );
      }
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    if (idu) {
      void charger(idu);
    }
  }, [idu, charger]);

  return (
    <Dialog open={piece !== null} onOpenChange={onOpenChange}>
      <DialogContent className="max-h-[85vh] max-w-3xl overflow-y-auto">
        <DialogHeader>
          <DialogTitle>Journal du document</DialogTitle>
          <DialogDescription>
            {piece?.nom_fichier ?? 'Document'} — tous les évènements du journal
            du CCFN associés à cet objet numérique.
          </DialogDescription>
        </DialogHeader>

        {piece ? (
          <div className="grid gap-3 rounded-lg border bg-muted/40 p-4 text-sm sm:grid-cols-2">
            <div>
              <p className="text-xs uppercase text-muted-foreground">IDU</p>
              <p className="break-all font-mono text-xs">{piece.idu ?? '—'}</p>
            </div>
            <div>
              <p className="text-xs uppercase text-muted-foreground">
                ID_ON_UTI
              </p>
              <p className="break-all font-mono text-xs">
                {piece.idu_on_uti ?? '—'}
              </p>
            </div>
            <div>
              <p className="text-xs uppercase text-muted-foreground">
                Taille de l&apos;ON
              </p>
              <p className="text-xs">{formatBytes(piece.taille_octets)}</p>
            </div>
            <div>
              <p className="text-xs uppercase text-muted-foreground">
                Algorithme d&apos;empreinte
              </p>
              <p className="font-mono text-xs">{piece.algo_empreinte}</p>
            </div>
            <div className="sm:col-span-2">
              <p className="text-xs uppercase text-muted-foreground">
                Empreinte calculée par le CCFN
              </p>
              <p className="break-all font-mono text-xs">
                {piece.empreinte ?? '—'}
              </p>
            </div>
          </div>
        ) : null}

        {isLoading ? (
          <div className="flex items-center justify-center gap-2 py-10 text-sm text-muted-foreground">
            <Loader2 className="h-4 w-4 animate-spin" />
            Lecture du journal…
          </div>
        ) : loadError ? (
          <p className="py-8 text-center text-sm text-destructive">
            {loadError}
          </p>
        ) : entrees.length === 0 ? (
          <p className="py-8 text-center text-sm text-muted-foreground">
            Aucun évènement journalisé pour ce document.
          </p>
        ) : (
          <ol className="space-y-3">
            {entrees
              .slice()
              .reverse()
              .map((entree) => {
                const succes = entree.statut_execution.code === 'ok';

                return (
                  <li
                    key={entree.sequence}
                    className="rounded-lg border p-3"
                  >
                    <div className="flex flex-wrap items-center justify-between gap-2">
                      <p className="font-medium">
                        {libelleFonction(entree.fonction)}
                      </p>
                      <span
                        className={cn(
                          'inline-flex rounded-full px-2 py-0.5 text-xs font-medium',
                          succes
                            ? 'bg-emerald-100 text-emerald-700'
                            : 'bg-destructive/10 text-destructive',
                        )}
                      >
                        {succes ? 'Correct' : 'Anomalie'}
                      </span>
                    </div>

                    <p className="mt-1 font-mono text-xs text-muted-foreground">
                      {entree.date_heure} · {formatDateJournal(entree.date_heure)}{' '}
                      UTC
                    </p>

                    <p className="mt-1 text-xs text-muted-foreground">
                      ID_UTI {entree.id_uti} · ID_CCFN {entree.id_ccfn}
                      {entree.id_cont ? ` · ID_CONT ${entree.id_cont}` : ''}
                    </p>

                    {!succes ? (
                      <p className="mt-2 text-xs text-destructive">
                        {entree.statut_execution.libelle}
                      </p>
                    ) : null}
                  </li>
                );
              })}
          </ol>
        )}
      </DialogContent>
    </Dialog>
  );
}
