import { useEffect, useId, useRef, useState } from "react";
import { ImageOff, ImagePlus, Loader2, Trash2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { getCachedStepImageUrl, getStepImageUrl, removeStepImage, uploadStepImage } from "@/services/stepImageService";
import type { TripStep } from "@/types";

function useStepImageUrl(imagePath?: string | null) {
  const [url, setUrl] = useState<string | null>(() => getCachedStepImageUrl(imagePath));
  const [error, setError] = useState(false);
  useEffect(() => {
    let active = true;
    let retryTimer: number | undefined;
    setUrl(getCachedStepImageUrl(imagePath));
    setError(false);
    const resolve = (attempt: number) => { if (!imagePath) return; void getStepImageUrl(imagePath)
      .then((value) => { if (active) setUrl(value); })
      .catch((cause) => { if (!active) return; if (attempt < 2) retryTimer = window.setTimeout(() => resolve(attempt + 1), 500 * (attempt + 1)); else { console.error("Impossible de signer l’image d’étape:", cause); setError(true); } }); };
    resolve(0);
    return () => { active = false; if (retryTimer) window.clearTimeout(retryTimer); };
  }, [imagePath]);
  return { url, error };
}

type StepImageVariant = "detail" | "thumbnail" | "planner-thumbnail";

export function StepImage({ step, variant = "detail", editable = false, onPersist }: { step: TripStep; variant?: StepImageVariant; editable?: boolean; onPersist?: (patch: Partial<TripStep>) => Promise<TripStep | null> }) {
  const id = useId(); const input = useRef<HTMLInputElement>(null);
  const { url, error: loadError } = useStepImageUrl(step.imagePath); const [busy, setBusy] = useState(false); const [phase, setPhase] = useState<"preparing" | "uploading" | null>(null); const [actionError, setActionError] = useState<string | null>(null);
  const choose = async (file?: File) => { if (!file || !onPersist || busy) return; setBusy(true); setPhase("preparing"); setActionError(null); let nextPath: string | null = null; let persisted = false; try { nextPath = await uploadStepImage(step.tripId, step.id, file, setPhase); const saved = await onPersist({ imagePath: nextPath }); if (!saved) throw new Error("L’image n’a pas été enregistrée."); persisted = true; if (step.imagePath) await removeStepImage(step.imagePath).catch((cause) => console.warn("Ancienne image non supprimée", cause)); } catch (cause) { if (nextPath && !persisted) await removeStepImage(nextPath).catch(() => undefined); setActionError(cause instanceof Error ? cause.message : "Impossible d’ajouter l’image."); } finally { setBusy(false); setPhase(null); if (input.current) input.current.value = ""; } };
  const remove = async () => { if (!step.imagePath || !onPersist || busy) return; setBusy(true); setActionError(null); try { const saved = await onPersist({ imagePath: "" }); if (!saved) throw new Error("Suppression non confirmée."); await removeStepImage(step.imagePath).catch((cause) => console.warn("Image orpheline à nettoyer", cause)); } catch (cause) { setActionError(cause instanceof Error ? cause.message : "Impossible de supprimer l’image."); } finally { setBusy(false); } };
  if (variant === "thumbnail" || variant === "planner-thumbnail") return step.imagePath ? <span className={`block aspect-[3/2] shrink-0 overflow-hidden rounded-lg bg-slate-200 ${variant === "planner-thumbnail" ? "w-full sm:w-28" : "w-20 sm:w-28"}`}>{url ? <img src={url} alt="" aria-hidden="true" className="block h-full w-full object-cover object-center" /> : loadError ? <span className="grid h-full w-full place-items-center bg-slate-100 text-slate-400" title="Image indisponible"><ImageOff className="h-5 w-5" aria-hidden="true" /></span> : <span className="block h-full w-full animate-pulse bg-slate-200" aria-hidden="true" />}</span> : null;
  if (!editable && !step.imagePath) return null;
  return <section aria-labelledby={`${id}-title`}><h3 id={`${id}-title`} className={editable ? "font-semibold text-secondary" : "sr-only"}>Image</h3>{step.imagePath && <div className="aspect-video w-full overflow-hidden rounded-xl bg-slate-200">{url ? <img src={url} alt={`Illustration de ${step.activity}`} className="block h-full w-full object-cover object-center" /> : loadError ? <div className="grid h-full place-items-center bg-slate-100 text-sm text-slate-500"><span className="flex items-center gap-2"><ImageOff className="h-5 w-5" />Image indisponible</span></div> : <div className="h-full w-full animate-pulse bg-slate-200" aria-hidden="true" />}</div>}{editable && <div className="mt-3 flex flex-wrap gap-2"><input ref={input} id={id} className="sr-only" type="file" accept="image/jpeg,image/png,image/webp" onChange={(event) => void choose(event.target.files?.[0])} /><Button type="button" size="sm" variant="outline" disabled={busy} onClick={() => input.current?.click()}>{busy ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <ImagePlus className="mr-2 h-4 w-4" />}{phase === "preparing" ? "Préparation de l’image…" : phase === "uploading" ? "Importation…" : step.imagePath ? "Remplacer" : "Ajouter une photo"}</Button>{step.imagePath && <Button type="button" size="sm" variant="ghost" disabled={busy} onClick={() => void remove()}><Trash2 className="mr-2 h-4 w-4" />Supprimer</Button>}</div>}{editable && (actionError || loadError) && <p role="alert" className="mt-2 text-sm text-destructive">{actionError || "Image indisponible."}</p>}</section>;
}

/** Adaptateur historique : tout le rendu reste centralisé dans StepImage. */
export function StepImageThumbnail({ step }: { step: TripStep }) {
  return <StepImage step={step} variant="thumbnail" />;
}
