import { useEffect, useRef, useState } from "react";
import { Check, Clock, Eye, EyeOff, FilePlus2, Loader2, MessageSquare, MoreHorizontal, Trash2, X } from "lucide-react";
import { format, parseISO } from "date-fns";
import { fr } from "date-fns/locale";
import { toast } from "sonner";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "@/components/ui/alert-dialog";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Textarea } from "@/components/ui/textarea";
import { DocumentsForStep } from "@/components/dashboard/documents/DocumentsForStep";
import { DocumentUploadForStep } from "@/components/dashboard/documents/DocumentUploadForStep";
import { PlannerStepValidations } from "@/components/dashboard/step/PlannerStepValidations";
import { StepComments } from "@/components/dashboard/StepComments";
import { EditStepDialog } from "@/components/dashboard/step/edit/EditStepDialog";
import { StepImage } from "@/components/dashboard/step/StepImage";
import { useTrips } from "@/contexts/TripContext";
import { getTripDays } from "@/services/itineraryGuards";
import { countTravelerStepDecisions, getTravelerStepDecisions } from "@/services/stepValidationSummary";
import { getStepTypeById } from "@/types/stepTypes";
import type { TripMember, TripStep } from "@/types";

interface Props { step: TripStep | null; members?: TripMember[]; startDate: string; endDate: string; onClose: () => void; editStepId?: string | null; onEditOpen: (id: string) => void; onEditClose: () => void; }
type SafeField = "activity" | "location" | "description" | "internalNotes" | "activityType" | "guideName" | "walkingLevel";
type SaveState = "idle" | "saving" | "saved" | "error";

export function PlannerStepPanel({ step, members, startDate, endDate, onClose, editStepId, onEditOpen, onEditClose }: Props) {
  const { updateTripStep, deleteTripStep, publishTripStep } = useTrips();
  const [draft, setDraft] = useState(step);
  const [schedule, setSchedule] = useState({ day: step?.day || 1, startTime: step?.startTime || step?.time || "", endTime: step?.endTime || "" });
  const [status, setStatus] = useState<SaveState>("idle");
  const [retryPatch, setRetryPatch] = useState<Partial<TripStep> | null>(null);
  const [showUpload, setShowUpload] = useState(false);
  const [showComments, setShowComments] = useState(false);
  const [showDelete, setShowDelete] = useState(false);
  const lock = useRef(false);

  useEffect(() => { setDraft(step); setSchedule({ day: step?.day || 1, startTime: step?.startTime || step?.time || "", endTime: step?.endTime || "" }); setStatus("idle"); }, [step]);
  useEffect(() => { if (!step) return; const escape = (event: KeyboardEvent) => { if (event.key === "Escape" && !editStepId && !showUpload && !showComments) onClose(); }; window.addEventListener("keydown", escape); return () => window.removeEventListener("keydown", escape); }, [editStepId, onClose, showComments, showUpload, step]);
  if (!step || !draft) return null;

  const decisions = getTravelerStepDecisions(step.validations, members);
  const counts = countTravelerStepDecisions(decisions);
  const stepType = getStepTypeById(step.stepType || "activity");
  const persist = async (patch: Partial<TripStep>) => {
    if (lock.current) return null;
    lock.current = true; setStatus("saving");
    try { const saved = await updateTripStep(step.tripId, step.id, patch); if (!saved) throw new Error("Mise à jour non confirmée"); setDraft(saved); setRetryPatch(null); setStatus("saved"); window.setTimeout(() => setStatus((value) => value === "saved" ? "idle" : value), 1800); return saved; }
    catch (error) { console.error(error); setRetryPatch(patch); setStatus("error"); return null; }
    finally { lock.current = false; }
  };
  const change = (field: SafeField, value: string) => setDraft((current) => current ? { ...current, [field]: value } : current);
  const saveField = (field: SafeField) => { const value = draft[field] || ""; if ((step[field] || "") !== value) void persist({ [field]: value }); };
  const togglePublication = async () => { if (lock.current) return; lock.current = true; setStatus("saving"); try { if (!await publishTripStep(step.tripId, step.id, !step.isPublished)) throw new Error("Non confirmé"); toast.success(step.isPublished ? "Étape masquée." : "Étape publiée."); setStatus("saved"); } catch (error) { console.error(error); setStatus("error"); toast.error("La visibilité n’a pas pu être modifiée."); } finally { lock.current = false; } };
  const remove = async () => { if (lock.current) return; lock.current = true; try { if (!await deleteTripStep(step.tripId, step.id)) throw new Error("Non confirmé"); toast.success("Étape supprimée."); onClose(); } catch (error) { console.error(error); toast.error("L’étape n’a pas pu être supprimée."); } finally { lock.current = false; } };

  return <>
    <div className="pointer-events-none fixed inset-0 z-40 bg-secondary/30 lg:hidden" aria-hidden />
    <aside className="fixed inset-y-0 right-0 z-50 w-full overflow-y-auto border-l bg-[#fffdf8] p-5 shadow-2xl sm:bottom-0 sm:top-20 sm:w-[420px] lg:w-[444px]" role="dialog" aria-modal="true" aria-labelledby="planner-step-panel-title">
      <header className="sticky -top-5 z-10 -mx-5 flex items-start gap-3 border-b bg-[#fffdf8]/95 px-5 pb-4 pt-5 backdrop-blur"><div className="min-w-0 flex-1"><p className="text-xs font-bold uppercase tracking-[.15em] text-primary">Étape sélectionnée</p><Label className="sr-only" htmlFor="step-title">Titre</Label><Input id="step-title" value={draft.activity} onChange={(e) => change("activity", e.target.value)} onBlur={() => saveField("activity")} className="mt-1 h-auto border-0 bg-transparent px-0 text-xl font-bold shadow-none focus-visible:ring-0" /></div><Button variant="ghost" size="icon" onClick={onClose} aria-label="Fermer le panneau"><X /></Button></header>
      <div className="mt-4 flex items-center justify-between gap-2"><div className="flex gap-2"><Badge variant={step.isPublished ? "default" : "outline"}>{step.isPublished ? "Publiée" : "Masquée"}</Badge><Badge variant="secondary">{stepType.label}</Badge></div><SaveStatus state={status} retry={retryPatch ? () => void persist(retryPatch) : undefined} /></div>
      <section className="mt-7 space-y-5"><h3 className="font-semibold text-secondary">Informations</h3><Field id="step-location" label="Lieu" value={draft.location || ""} onChange={(v) => change("location", v)} onBlur={() => saveField("location")} /><div className="grid gap-2"><Label htmlFor="step-description">Description</Label><Textarea id="step-description" value={draft.description || ""} onChange={(e) => change("description", e.target.value)} onBlur={() => saveField("description")} rows={4} placeholder="Ce que le voyageur doit savoir" /></div></section>
      <div className="mt-7 border-t pt-6"><StepImage step={step} editable onPersist={persist} /></div>
      <section className="mt-7 border-t pt-6"><h3 className="font-semibold text-secondary">Jour et horaires</h3><p className="mt-1 text-xs text-muted-foreground">Application explicite pour préserver la cohérence des validations.</p><div className="mt-4 grid gap-4 sm:grid-cols-2"><div className="grid gap-2 sm:col-span-2"><Label htmlFor="step-day">Jour</Label><Select value={String(schedule.day)} onValueChange={(v) => setSchedule((s) => ({ ...s, day: Number(v) }))}><SelectTrigger id="step-day"><SelectValue /></SelectTrigger><SelectContent>{getTripDays(startDate, endDate).map(({ day, date }) => <SelectItem key={day} value={String(day)}>Jour {day} — {format(parseISO(date), "EEEE d MMMM", { locale: fr })}</SelectItem>)}</SelectContent></Select></div><div className="grid gap-2"><Label htmlFor="step-start">Début</Label><Input id="step-start" type="time" value={schedule.startTime} onChange={(e) => setSchedule((s) => ({ ...s, startTime: e.target.value }))} /></div><div className="grid gap-2"><Label htmlFor="step-end">Fin</Label><Input id="step-end" type="time" value={schedule.endTime} onChange={(e) => setSchedule((s) => ({ ...s, endTime: e.target.value }))} /></div></div><Button size="sm" variant="outline" className="mt-4" onClick={() => void persist({ day: schedule.day, startTime: schedule.startTime, time: schedule.startTime, endTime: schedule.endTime })}><Clock className="mr-2 h-4 w-4" />Appliquer le planning</Button></section>
      <details className="mt-7 border-t pt-6"><summary className="cursor-pointer font-semibold text-secondary">Détails pratiques</summary><div className="mt-4 space-y-4"><Field id="activity-type" label="Type d’activité" value={draft.activityType || ""} onChange={(v) => change("activityType", v)} onBlur={() => saveField("activityType")} /><Field id="guide" label="Guide ou contact" value={draft.guideName || ""} onChange={(v) => change("guideName", v)} onBlur={() => saveField("guideName")} /><Field id="walking" label="Accessibilité / niveau de marche" value={draft.walkingLevel || ""} onChange={(v) => change("walkingLevel", v)} onBlur={() => saveField("walkingLevel")} /></div></details>
      <details className="mt-6 border-t pt-6"><summary className="cursor-pointer font-semibold text-secondary">Validation des voyageurs<span className="mt-1 block text-sm font-normal text-muted-foreground">{counts.approved} approuvé · {counts.rejected} refusé · {counts.pending} en attente</span></summary><PlannerStepValidations validations={step.validations} members={members} showSummary={false} /></details>
      <div className="mt-6 border-t pt-6"><DocumentsForStep tripId={step.tripId} stepId={step.id} isPlanner /></div>
      <section className="mt-6 border-t pt-6"><Label htmlFor="internal-notes" className="font-semibold text-secondary">Notes internes</Label><Textarea id="internal-notes" className="mt-3" value={draft.internalNotes || ""} onChange={(e) => change("internalNotes", e.target.value)} onBlur={() => saveField("internalNotes")} rows={3} placeholder="Visibles uniquement par le Planner" /></section>
      <footer className="sticky bottom-0 -mx-5 mt-7 flex flex-col gap-2 border-t bg-[#fffdf8]/95 px-5 py-4 backdrop-blur">
        <Button variant={step.isPublished ? "outline" : "default"} className="w-full" disabled={status === "saving"} onClick={() => void togglePublication()}>
          {step.isPublished ? <EyeOff className="mr-2 h-4 w-4" /> : <Eye className="mr-2 h-4 w-4" />}
          {step.isPublished ? "Masquer aux voyageurs" : "Publier pour les voyageurs"}
        </Button>
        <div className="flex gap-2">
          <Button variant="outline" className="flex-1" onClick={() => setShowUpload(true)}><FilePlus2 className="mr-2 h-4 w-4" />Documents</Button>
          <Button variant="outline" className="flex-1" onClick={() => setShowComments(true)}><MessageSquare className="mr-2 h-4 w-4" />Commentaires ({step.comments.length})</Button>
          <DropdownMenu><DropdownMenuTrigger asChild><Button variant="ghost" size="icon" aria-label="Plus d’actions"><MoreHorizontal /></Button></DropdownMenuTrigger><DropdownMenuContent align="end"><DropdownMenuItem onClick={() => onEditOpen(step.id)}>Édition avancée</DropdownMenuItem><DropdownMenuSeparator /><DropdownMenuItem className="text-destructive" onClick={() => setShowDelete(true)}><Trash2 className="mr-2 h-4 w-4" />Supprimer</DropdownMenuItem></DropdownMenuContent></DropdownMenu>
        </div>
      </footer>
    </aside>
    {editStepId === step.id && <EditStepDialog isOpen onClose={onEditClose} step={step} tripId={step.tripId} />}{showUpload && <DocumentUploadForStep tripId={step.tripId} stepId={step.id} isOpen onClose={() => setShowUpload(false)} />}{showComments && <StepComments isOpen onClose={() => setShowComments(false)} tripId={step.tripId} step={step} />}
    <AlertDialog open={showDelete} onOpenChange={setShowDelete}><AlertDialogContent><AlertDialogHeader><AlertDialogTitle>Supprimer cette étape ?</AlertDialogTitle><AlertDialogDescription>Ses documents et commentaires seront également supprimés. Cette action est irréversible.</AlertDialogDescription></AlertDialogHeader><AlertDialogFooter><AlertDialogCancel>Annuler</AlertDialogCancel><AlertDialogAction className="bg-destructive text-destructive-foreground" onClick={(e) => { e.preventDefault(); void remove(); }}>Supprimer définitivement</AlertDialogAction></AlertDialogFooter></AlertDialogContent></AlertDialog>
  </>;
}

function Field({ id, label, value, onChange, onBlur }: { id: string; label: string; value: string; onChange: (value: string) => void; onBlur: () => void }) { return <div className="grid gap-2"><Label htmlFor={id}>{label}</Label><Input id={id} value={value} onChange={(e) => onChange(e.target.value)} onBlur={onBlur} /></div>; }
function SaveStatus({ state, retry }: { state: SaveState; retry?: () => void }) { return <div role="status" aria-live="polite" className="text-xs text-muted-foreground">{state === "saving" && <span className="flex items-center gap-1"><Loader2 className="h-3.5 w-3.5 animate-spin" />Enregistrement…</span>}{state === "saved" && <span className="flex items-center gap-1 text-emerald-700"><Check className="h-3.5 w-3.5" />Enregistré</span>}{state === "error" && <button className="text-destructive underline" onClick={retry}>Impossible d’enregistrer · Réessayer</button>}</div>; }
