"use client"

import { useEffect, useMemo, useRef, useState } from "react"
import { addDays, addHours } from "date-fns"
import { toast } from "sonner"
import {
  AlignLeft,
  CalendarDays,
  MapPin,
  Repeat,
  Trash2,
  Users,
  Video,
} from "lucide-react"
import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogContent,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select"
import { Textarea } from "@/components/ui/textarea"
import { AgendaEventScheduleFields, agendaScheduleFieldCount } from "@/components/agenda/agenda-event-schedule-fields"
import { AgendaGuestPicker } from "@/components/agenda/agenda-guest-picker"
import { AgendaVideoToggle } from "@/components/agenda/agenda-video-toggle"
import {
  createAgendaEventWithVideo,
  saveAgendaEventEdit,
} from "@/lib/agenda/agenda-save-with-video"
import {
  useCreateAgendaEvent,
  useCreateAgendaMeetLink,
  useDeleteAgendaEvent,
  useUpdateAgendaEvent,
} from "@/lib/api/hooks/use-calendar-mutations"
import { AGENDA_COLOR_PALETTE } from "@/lib/agenda/agenda-colors"
import { calendarColor } from "@/lib/agenda/agenda-events"
import { describeRRule, recurrenceOptionsFor } from "@/lib/agenda/agenda-recurrence"
import type {
  AgendaCalendar,
  AgendaEvent,
  AgendaEventAttendee,
  AgendaEventDraft,
} from "@/lib/agenda/agenda-types"
import { useEffectiveAgendaSettings } from "@/lib/agenda/use-effective-agenda-settings"
import { cn } from "@/lib/utils"

export interface AgendaEventDialogState {
  mode: "create" | "edit"
  draft: AgendaEventDraft
  /** Présent en édition. */
  event?: AgendaEvent
}

export function AgendaEventDialog({
  state,
  onClose,
  calendars,
  userEmail,
  onDraftChange,
}: {
  state: AgendaEventDialogState | null
  onClose: () => void
  calendars: AgendaCalendar[]
  userEmail?: string
  onDraftChange?: (draft: AgendaEventDraft) => void
}) {
  const createMutation = useCreateAgendaEvent()
  const updateMutation = useUpdateAgendaEvent()
  const deleteMutation = useDeleteAgendaEvent()
  const meetLinkMutation = useCreateAgendaMeetLink()
  const { buttonSnapMinutes, defaultVideoProvider } = useEffectiveAgendaSettings()

  const [title, setTitle] = useState("")
  const [allDay, setAllDay] = useState(false)
  const [start, setStart] = useState(() => new Date())
  const [end, setEnd] = useState(() => new Date())
  const [calendarId, setCalendarId] = useState("")
  const [rrule, setRRule] = useState("")
  const [color, setColor] = useState("")
  const [location, setLocation] = useState("")
  const [description, setDescription] = useState("")
  const [attendees, setAttendees] = useState<AgendaEventAttendee[]>([])
  const [includeVideo, setIncludeVideo] = useState(false)
  const [meetUrl, setMeetUrl] = useState("")
  const titleRef = useRef<HTMLInputElement>(null)

  const open = state !== null
  const isEdit = state?.mode === "edit"

  useEffect(() => {
    if (!state) return
    const d = state.draft
    setTitle(d.title)
    setAllDay(d.allDay)
    setStart(d.start)
    setEnd(d.allDay ? addDays(d.end, -1) : d.end)
    setCalendarId(d.calendarId || calendars[0]?.id || "")
    setRRule(d.rrule ?? "")
    setColor(d.color ?? "")
    setLocation(d.location ?? "")
    setDescription(d.description ?? "")
    setAttendees(d.attendees ?? [])
    setIncludeVideo(Boolean(d.includeVideo || state.event?.meetUrl))
    setMeetUrl(state.event?.meetUrl ?? "")
    if (state.mode === "create") {
      const timer = window.setTimeout(() => titleRef.current?.focus(), 0)
      return () => window.clearTimeout(timer)
    }
  }, [state, calendars])

  useEffect(() => {
    if (allDay) setIncludeVideo(false)
  }, [allDay])

  const recurrenceOptions = useMemo(() => {
    const options = recurrenceOptionsFor(start)
    if (rrule && !options.some((o) => o.value === rrule)) {
      options.push({ value: rrule, label: describeRRule(rrule) })
    }
    return options
  }, [start, rrule])

  const pending =
    createMutation.isPending ||
    updateMutation.isPending ||
    deleteMutation.isPending ||
    meetLinkMutation.isPending

  const buildDraft = (): AgendaEventDraft | null => {
    if (!calendarId) return null
    let eventStart = start
    let eventEnd = allDay ? addDays(end, 1) : end
    if (allDay && eventEnd <= eventStart) eventEnd = addDays(eventStart, 1)
    if (!allDay && eventEnd <= eventStart) eventEnd = addHours(eventStart, 1)
    return {
      title,
      start: eventStart,
      end: eventEnd,
      allDay,
      calendarId,
      description,
      location,
      attendees,
      rrule,
      color: color || undefined,
      includeVideo: includeVideo && !allDay,
    }
  }

  useEffect(() => {
    if (!open || isEdit || !onDraftChange) return
    const draft = buildDraft()
    if (draft) onDraftChange(draft)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [
    open,
    isEdit,
    title,
    allDay,
    start,
    end,
    calendarId,
    color,
    includeVideo,
    onDraftChange,
  ])

  const calendar = calendars.find((c) => c.id === calendarId) ?? calendars[0]

  const submit = async () => {
    const draft = buildDraft()
    if (!draft || !calendar) return
    try {
      if (isEdit && state?.event) {
        await saveAgendaEventEdit({
          draft,
          path: state.event.path,
          etag: state.event.etag,
          master: state.event.master,
          includeVideo: includeVideo && !allDay,
          meetUrl,
          videoProvider: defaultVideoProvider,
          updateMutation,
          meetLinkMutation,
        })
        toast.success("Événement mis à jour")
      } else {
        await createAgendaEventWithVideo({
          draft,
          calendar,
          userEmail,
          includeVideo: includeVideo && !allDay,
          videoProvider: defaultVideoProvider,
          createMutation,
          meetLinkMutation,
        })
        toast.success(
          includeVideo && !allDay ? "Événement et visio créés" : "Événement créé",
        )
      }
      onClose()
    } catch {
      toast.error("Impossible d'enregistrer l'événement")
    }
  }

  const remove = async () => {
    if (!state?.event) return
    try {
      await deleteMutation.mutateAsync({ path: state.event.path })
      toast.success("Événement supprimé")
      onClose()
    } catch {
      toast.error("Impossible de supprimer l'événement")
    }
  }

  const handleVideoChange = (enabled: boolean) => {
    setIncludeVideo(enabled)
    if (!enabled) setMeetUrl("")
  }

  const scheduleTabCount = agendaScheduleFieldCount({
    allDay,
    showAllDayToggle: true,
    compact: false,
  })
  const tab = (offset: number) => 2 + scheduleTabCount + offset

  return (
    <Dialog
      open={open}
      onOpenChange={(o) => {
        if (!o) onClose()
      }}
    >
      <DialogContent
        className="flex max-h-[90vh] flex-col gap-0 overflow-hidden p-0 sm:max-w-xl"
        aria-describedby={undefined}
      >
        <DialogHeader className="sr-only">
          <DialogTitle>
            {isEdit ? "Modifier l'événement" : "Nouvel événement"}
          </DialogTitle>
        </DialogHeader>

        <div className="flex flex-1 flex-col gap-4 overflow-y-auto px-5 pb-4 pt-4">
          <Input
            ref={titleRef}
            value={title}
            tabIndex={1}
            autoFocus={!isEdit}
            onChange={(e) => setTitle(e.target.value)}
            placeholder="Ajouter un titre"
            className="h-11 rounded-none border-0 border-b-2 border-border/60 !bg-transparent px-1 !text-xl shadow-none focus-visible:border-primary focus-visible:ring-0"
          />

          <AgendaEventScheduleFields
            start={start}
            end={end}
            allDay={allDay}
            stepMinutes={buttonSnapMinutes}
            tabIndexBase={2}
            showRowLabels
            showAllDayToggle
            onAllDayChange={setAllDay}
            onChange={(nextStart, nextEnd) => {
              setStart(nextStart)
              setEnd(allDay ? nextEnd : nextEnd)
            }}
          />

          <div className="flex items-center gap-3">
            <Repeat className="size-5 shrink-0 text-muted-foreground" />
            <Select value={rrule || "none"} onValueChange={(v) => setRRule(v === "none" ? "" : v)}>
              <SelectTrigger tabIndex={tab(0)} className="h-9 w-fit min-w-52 border-0 bg-muted/60 shadow-none">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {recurrenceOptions.map((o) => (
                  <SelectItem key={o.value || "none"} value={o.value || "none"}>
                    {o.label}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>

          <div className="flex items-start gap-3">
            <Users className="mt-2 size-5 shrink-0 text-muted-foreground" />
            <div className="min-w-0 flex-1">
              <AgendaGuestPicker
                attendees={attendees}
                onChange={setAttendees}
                organizerEmail={userEmail}
                tabIndex={tab(1)}
              />
            </div>
          </div>

          {!allDay && defaultVideoProvider !== "none" ? (
            <div className="flex items-start gap-3">
              <Video className="mt-2 size-5 shrink-0 text-muted-foreground" aria-hidden />
              <AgendaVideoToggle
                provider={defaultVideoProvider}
                enabled={includeVideo}
                meetUrl={includeVideo ? meetUrl : undefined}
                onEnabledChange={handleVideoChange}
                pending={pending}
                tabIndex={tab(2)}
              />
            </div>
          ) : null}

          <div className="flex items-center gap-3">
            <MapPin className="size-5 shrink-0 text-muted-foreground" />
            <Input
              value={location}
              tabIndex={tab(3)}
              onChange={(e) => setLocation(e.target.value)}
              placeholder="Ajouter un lieu"
              className="h-9 flex-1"
            />
          </div>

          <div className="flex items-start gap-3">
            <AlignLeft className="mt-2 size-5 shrink-0 text-muted-foreground" />
            <Textarea
              value={description}
              tabIndex={tab(4)}
              onChange={(e) => setDescription(e.target.value)}
              placeholder="Ajouter une description"
              className="min-h-20 flex-1"
            />
          </div>

          <div className="flex flex-wrap items-center gap-3">
            <CalendarDays className="size-5 shrink-0 text-muted-foreground" />
            <Select value={calendarId} onValueChange={setCalendarId} disabled={isEdit}>
              <SelectTrigger tabIndex={tab(5)} className="h-9 w-fit min-w-40 border-0 bg-muted/60 shadow-none">
                <SelectValue placeholder="Agenda" />
              </SelectTrigger>
              <SelectContent>
                {calendars.map((cal) => (
                  <SelectItem key={cal.id} value={cal.id}>
                    <span className="flex items-center gap-2">
                      <span
                        className="size-3 rounded-full"
                        style={{ backgroundColor: calendarColor(cal) }}
                      />
                      {cal.display_name}
                    </span>
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <div className="flex items-center gap-1.5">
              {AGENDA_COLOR_PALETTE.slice(0, 8).map((c, i) => (
                <button
                  key={c.value}
                  type="button"
                  tabIndex={tab(6 + i)}
                  title={c.label}
                  aria-label={`Couleur ${c.label}`}
                  onClick={() => setColor(color === c.value ? "" : c.value)}
                  className={cn(
                    "size-5 rounded-full transition-transform hover:scale-110",
                    color === c.value &&
                      "ring-2 ring-foreground/60 ring-offset-1 ring-offset-background",
                  )}
                  style={{ backgroundColor: c.value }}
                />
              ))}
            </div>
          </div>
        </div>

        <DialogFooter className="flex-row items-center border-t border-border/60 px-5 py-3">
          {isEdit && (
            <Button
              variant="ghost"
              tabIndex={tab(14)}
              className="mr-auto gap-2 text-destructive hover:text-destructive"
              disabled={pending}
              onClick={() => void remove()}
            >
              <Trash2 className="size-4" /> Supprimer
            </Button>
          )}
          <Button variant="ghost" tabIndex={tab(15)} onClick={onClose} disabled={pending}>
            Annuler
          </Button>
          <Button
            tabIndex={tab(16)}
            onClick={() => void submit()}
            disabled={pending || !calendarId}
            className="rounded-full px-6"
          >
            Enregistrer
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}
