"use client";

import {
  FileImage,
  FileText,
  FileType2,
  X,
} from "lucide-react";

import {
  fichierName,
  fichierPath,
  type DocumentFichier,
} from "@/types/document";

export function formatFileSize(bytes: number): string {
  if (!Number.isFinite(bytes) || bytes < 0) return "—";
  if (bytes < 1024) return `${bytes} o`;
  const kb = bytes / 1024;
  if (kb < 1024) return `${kb.toFixed(1)} Ko`;
  const mb = kb / 1024;
  return `${mb.toFixed(2)} Mo`;
}

function fileExtension(name: string): string {
  const idx = name.lastIndexOf(".");
  if (idx < 0) return "";
  return name.slice(idx + 1).toLowerCase();
}

export type FileKind = "image" | "pdf" | "doc" | "other";

export function fileKindFromName(name: string | null | undefined): FileKind {
  const n = (name ?? "").toLowerCase();
  const ext = fileExtension(n);
  if (["jpg", "jpeg", "png", "gif", "webp", "bmp", "svg"].includes(ext))
    return "image";
  if (ext === "pdf") return "pdf";
  if (ext === "doc" || ext === "docx") return "doc";
  return "other";
}

export function fileKindFromMime(mime: string | null | undefined): FileKind | null {
  const m = (mime ?? "").toLowerCase();
  if (!m) return null;
  if (m.startsWith("image/")) return "image";
  if (m === "application/pdf") return "pdf";
  if (
    m === "application/msword" ||
    m ===
      "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
  ) {
    return "doc";
  }
  return "other";
}

export function documentFichierKind(f: DocumentFichier): FileKind {
  if (typeof f === "object" && f) {
    const url = fichierPath(f);
    const fromName = fileKindFromName(f.nom ?? f.name ?? url);
    if (fromName !== "other") return fromName;
  }
  return fileKindFromName(fichierPath(f));
}

function normalizeStorageBaseUrl(): string {
  const raw = process.env.NEXT_PUBLIC_APP_STORAGE_URL?.trim() ?? "";
  if (!raw) return "";
  return raw.endsWith("/") ? raw : `${raw}/`;
}

/** Résout une URL affichable pour un fichier stocké côté API.
 *  Utilise toujours NEXT_PUBLIC_APP_STORAGE_URL comme base,
 *  même si l'API renvoie une URL absolue (qui peut avoir une base incorrecte).
 */
export function resolveFichierUrl(
  value: string | null | undefined
): string | null {
  if (!value) return null;
  const raw = value.trim();
  if (!raw) return null;

  const base = normalizeStorageBaseUrl();

  /* Si l'API renvoie une URL absolue, on extrait le chemin relatif
     après "storage/" pour le reconstruire avec la bonne base. */
  if (/^https?:\/\//i.test(raw)) {
    if (!base) return raw; /* pas de base configurée : retour tel quel */
    const storageIdx = raw.indexOf("/storage/");
    if (storageIdx !== -1) {
      const rel = raw.slice(storageIdx + "/storage/".length);
      return `${base}${rel}`;
    }
    return raw; /* URL sans /storage/ : on ne touche pas */
  }

  if (!base) return raw;
  let path = raw.replace(/\\/g, "/").replace(/^\/+/, "");
  if (path.startsWith("storage/")) path = path.slice("storage/".length);
  if (path.startsWith("public/")) path = path.slice("public/".length);
  return `${base}${path}`;
}

export function documentFichierDisplayUrl(f: DocumentFichier): string | null {
  return resolveFichierUrl(fichierPath(f));
}

function FileKindIcon({
  kind,
  className,
}: {
  kind: FileKind;
  className?: string;
}) {
  if (kind === "image")
    return <FileImage className={className} aria-hidden />;
  if (kind === "pdf") return <FileType2 className={className} aria-hidden />;
  if (kind === "doc") return <FileText className={className} aria-hidden />;
  return <FileText className={className} aria-hidden />;
}

function kindBadgeClasses(kind: FileKind): string {
  if (kind === "pdf") return "bg-red-50 text-red-600";
  if (kind === "doc") return "bg-blue-50 text-blue-600";
  if (kind === "image") return "bg-emerald-50 text-emerald-600";
  return "bg-muted text-muted-foreground";
}

function kindBadgeLabel(kind: FileKind): string {
  if (kind === "pdf") return "PDF";
  if (kind === "doc") return "DOC";
  if (kind === "image") return "Image";
  return "Fichier";
}

export type FichierGalleryItem = {
  key: string;
  name: string;
  url: string | null;
  kind: FileKind;
  size?: number;
};

export function fichiersToGalleryItems(
  fichiers: DocumentFichier[],
  keyPrefix: string
): FichierGalleryItem[] {
  return fichiers.map((f, idx) => ({
    key: `${keyPrefix}-${idx}`,
    name: fichierName(f) || `Fichier ${idx + 1}`,
    url: documentFichierDisplayUrl(f),
    kind: documentFichierKind(f),
  }));
}

function GalleryTile({
  item,
  onRemove,
  size = "md",
}: {
  item: FichierGalleryItem;
  onRemove?: () => void;
  size?: "sm" | "md";
}) {
  const dims =
    size === "sm" ? "h-16 w-16" : "h-28 w-full sm:h-32";
  const iconSize = size === "sm" ? "h-6 w-6" : "h-10 w-10";
  const isImage = item.kind === "image" && item.url;

  const inner = (
    <div
      className={`relative flex ${dims} items-center justify-center overflow-hidden rounded-md border border-border/70 bg-muted/30`}
      title={item.name}
    >
      {isImage ? (
        // eslint-disable-next-line @next/next/no-img-element
        <img
          src={item.url ?? undefined}
          alt={item.name}
          className="h-full w-full object-cover"
          loading="lazy"
        />
      ) : (
        <FileKindIcon
          kind={item.kind}
          className={`${iconSize} ${
            item.kind === "pdf"
              ? "text-red-500"
              : item.kind === "doc"
                ? "text-blue-500"
                : "text-muted-foreground"
          }`}
        />
      )}
      {size === "md" && (
        <span
          className={`absolute left-1.5 top-1.5 rounded px-1.5 py-0.5 text-[10px] font-semibold ${kindBadgeClasses(
            item.kind
          )}`}
        >
          {kindBadgeLabel(item.kind)}
        </span>
      )}
      {onRemove && (
        <button
          type="button"
          onClick={(e) => {
            e.preventDefault();
            e.stopPropagation();
            onRemove();
          }}
          aria-label="Retirer ce fichier"
          className="absolute right-1 top-1 inline-flex h-6 w-6 items-center justify-center rounded-full bg-background/90 text-destructive shadow-sm ring-1 ring-border hover:bg-destructive hover:text-destructive-foreground"
        >
          <X className="h-3 w-3" aria-hidden />
        </button>
      )}
    </div>
  );

  if (item.url) {
    return (
      <a
        href={item.url}
        target="_blank"
        rel="noreferrer"
        className="group block"
      >
        {inner}
        <p className="mt-1 truncate text-[11px] text-foreground group-hover:text-primary">
          {item.name}
        </p>
        {typeof item.size === "number" && (
          <p className="text-[10px] text-muted-foreground">
            {formatFileSize(item.size)}
          </p>
        )}
      </a>
    );
  }

  return (
    <div className="block">
      {inner}
      <p className="mt-1 truncate text-[11px] text-foreground">{item.name}</p>
      {typeof item.size === "number" && (
        <p className="text-[10px] text-muted-foreground">
          {formatFileSize(item.size)}
        </p>
      )}
    </div>
  );
}

/** Grille type « Documents » : aperçus, lien nouvel onglet, retrait optionnel. */
export function FichierFileGallery({
  items,
  size = "md",
  onRemoveAt,
  emptyText = "Aucun fichier.",
}: {
  items: FichierGalleryItem[];
  size?: "sm" | "md";
  onRemoveAt?: (index: number) => void;
  emptyText?: string;
}) {
  if (items.length === 0) {
    return <p className="text-sm text-muted-foreground">{emptyText}</p>;
  }
  const gridCols =
    size === "sm"
      ? "grid-cols-4 sm:grid-cols-6"
      : "grid-cols-2 sm:grid-cols-3";
  return (
    <div className={`grid gap-3 ${gridCols}`}>
      {items.map((item, idx) => (
        <GalleryTile
          key={item.key}
          item={item}
          size={size}
          onRemove={onRemoveAt ? () => onRemoveAt(idx) : undefined}
        />
      ))}
    </div>
  );
}

/** Empilement compact pour une cellule de tableau (4 miniatures max). */
export function FichierGalleryMiniStack({
  fichiers,
  rowKey,
}: {
  fichiers: DocumentFichier[];
  rowKey: string;
}) {
  if (fichiers.length === 0) return <>—</>;
  return (
    <div className="flex items-center gap-2">
      <div className="flex -space-x-1.5">
        {fichiers.slice(0, 4).map((f, idx) => {
          const kind = documentFichierKind(f);
          const url = documentFichierDisplayUrl(f);
          const isImage = kind === "image" && url;
          return (
            <span
              key={`mini-${rowKey}-${idx}`}
              title={fichierName(f) || `Fichier ${idx + 1}`}
              className={`flex h-8 w-8 items-center justify-center overflow-hidden rounded border-2 border-background ${
                isImage ? "" : kindBadgeClasses(kind)
              }`}
            >
              {isImage ? (
                // eslint-disable-next-line @next/next/no-img-element
                <img
                  src={url ?? undefined}
                  alt={fichierName(f) || ""}
                  className="h-full w-full object-cover"
                  loading="lazy"
                />
              ) : (
                <FileKindIcon kind={kind} className="h-3.5 w-3.5" />
              )}
            </span>
          );
        })}
      </div>
      <span className="text-xs text-muted-foreground">
        {fichiers.length} fichier{fichiers.length > 1 ? "s" : ""}
      </span>
    </div>
  );
}
