"use client"

import { useEffect, useMemo, useState } from "react"
import { createClient } from "@/lib/supabase/client"
import { Button } from "@/components/ui/button"
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { Calendar } from "@/components/ui/calendar"
import { Textarea } from "@/components/ui/textarea"
import { FieldGroup, Field, FieldLabel } from "@/components/ui/field"
import { Spinner } from "@/components/ui/spinner"
import { format, addMinutes, setHours, setMinutes, startOfDay, isBefore } from "date-fns"
import { es } from "date-fns/locale"
import { CalendarIcon } from "lucide-react"
import type { Database } from "@/lib/supabase/database.types"
import {
  bookingFieldsToSlotStarts,
  buildDurationOptionsMinutes,
  normalizeResourceTypeBookingFields,
  parseTimeToMinutesSinceMidnight,
  DEFAULT_BOOKING_FIELDS,
  type ResourceTypeBookingFields,
} from "@/lib/booking"
import { cn } from "@/lib/utils"
import { toast } from "sonner"
import { getResourceLocationPathLabel } from "@/lib/resources/location"

type ResourceOption = Database["public"]["Tables"]["resources"]["Row"] & {
  resource_types: {
    name: string
    booking_window_start?: string | null
    booking_window_end?: string | null
    slot_size?: string | null
    time_granularity?: string | null
  } | null
}

type ReservationWithResource = Database["public"]["Tables"]["reservations"]["Row"] & {
  resources: {
    name: string
    floor: string | null
    resource_types: { name: string; slug: string } | null
  } | null
}

type ReservationEditorDialogProps = {
  open: boolean
  mode: "edit" | "rebook"
  reservation: ReservationWithResource | null
  onClose: () => void
  onSaved: () => void
}

function formatDurationLabel(minutes: number): string {
  if (minutes >= 60 && minutes % 60 === 0) {
    const h = minutes / 60
    return h === 1 ? "1 hora" : `${h} horas`
  }
  if (minutes >= 60) {
    const h = Math.floor(minutes / 60)
    const m = minutes % 60
    return m === 0 ? (h === 1 ? "1 hora" : `${h} horas`) : `${h} h ${m} min`
  }
  return `${minutes} minutos`
}

function getNextAvailableStart(fields: ResourceTypeBookingFields) {
  const now = new Date()
  const day = startOfDay(now)
  const starts = bookingFieldsToSlotStarts(fields)
  for (const t of starts) {
    const [h, m] = t.split(":").map(Number)
    const candidate = setMinutes(setHours(day, h), m)
    if (candidate.getTime() > now.getTime()) return candidate
  }
  const nextDay = addMinutes(day, 24 * 60)
  const firstMin = parseTimeToMinutesSinceMidnight(fields.booking_window_start)
  const h = Math.floor(firstMin / 60)
  const mi = firstMin % 60
  return setMinutes(setHours(nextDay, h), mi)
}

export function ReservationEditorDialog({
  open,
  mode,
  reservation,
  onClose,
  onSaved,
}: ReservationEditorDialogProps) {
  const supabase = useMemo(() => createClient(), [])
  const [resources, setResources] = useState<ResourceOption[]>([])
  const [loadingResources, setLoadingResources] = useState(false)
  const [submitting, setSubmitting] = useState(false)
  const [error, setError] = useState<string | null>(null)

  const [resourceId, setResourceId] = useState("")
  const [selectedDate, setSelectedDate] = useState<Date>(() => new Date())
  const [startTime, setStartTime] = useState("09:00")
  const [duration, setDuration] = useState(60)
  const [notes, setNotes] = useState("")

  useEffect(() => {
    if (!open) return
    let cancelled = false
    const load = async () => {
      setLoadingResources(true)
      const { data } = await supabase
        .from("resources")
        .select(
          "*, resource_types(name, booking_window_start, booking_window_end, slot_size, time_granularity)",
        )
        .eq("is_active", true)
        .order("name")

      if (cancelled) return

      setResources((data ?? []) as ResourceOption[])
      setLoadingResources(false)
    }
    void load()
    return () => {
      cancelled = true
    }
  }, [open, supabase])

  useEffect(() => {
    if (!open || !reservation) return
    if (mode === "rebook" && resources.length === 0) return

    const currentStart = new Date(reservation.start_at)
    const currentEnd = new Date(reservation.end_at)
    const durationMinutes = Math.max(30, Math.round((currentEnd.getTime() - currentStart.getTime()) / 60000))

    if (mode === "edit") {
      setResourceId(reservation.resource_id)
      setSelectedDate(currentStart)
      setStartTime(format(currentStart, "HH:mm"))
      setDuration(durationMinutes)
    } else {
      const res = resources.find((r) => r.id === reservation.resource_id)
      const fields = normalizeResourceTypeBookingFields(
        res?.resource_types as Partial<ResourceTypeBookingFields> | null | undefined,
      )
      const nextStart = getNextAvailableStart(fields)
      setResourceId(reservation.resource_id)
      setSelectedDate(nextStart)
      setStartTime(format(nextStart, "HH:mm"))
      setDuration(durationMinutes)
    }

    setNotes(reservation.notes ?? "")
    setError(null)
  }, [open, reservation, mode, resources])

  const selectedResourceRow = useMemo(() => resources.find((r) => r.id === resourceId), [resources, resourceId])
  const bookingFields = useMemo(
    () =>
      normalizeResourceTypeBookingFields(
        selectedResourceRow?.resource_types as Partial<ResourceTypeBookingFields> | null | undefined,
      ),
    [selectedResourceRow],
  )
  const slotOptions = useMemo(() => {
    const s = bookingFieldsToSlotStarts(bookingFields)
    return s.length > 0 ? s : bookingFieldsToSlotStarts(DEFAULT_BOOKING_FIELDS)
  }, [bookingFields])

  const durationOptions = useMemo(
    () => buildDurationOptionsMinutes({ startTimeHHmm: startTime, date: selectedDate, fields: bookingFields }),
    [startTime, selectedDate, bookingFields],
  )

  useEffect(() => {
    if (slotOptions.length === 0) return
    if (!slotOptions.includes(startTime)) setStartTime(slotOptions[0])
  }, [resourceId, slotOptions, startTime])

  useEffect(() => {
    if (durationOptions.length === 0) return
    setDuration((d) => (durationOptions.includes(d) ? d : durationOptions[0]))
  }, [durationOptions])

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault()
    if (!reservation) return
    if (!resourceId) {
      setError("Selecciona un recurso")
      return
    }

    setSubmitting(true)
    setError(null)

    const [hour, minute] = startTime.split(":").map(Number)
    const startAt = setMinutes(setHours(selectedDate, hour), minute)
    const endAt = addMinutes(startAt, duration)

    const endpoint =
      mode === "edit" ? `/api/reservations/${encodeURIComponent(reservation.id)}` : "/api/reservations"
    const method = mode === "edit" ? "PATCH" : "POST"

    const response = await fetch(endpoint, {
      method,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        resourceId,
        startAt: startAt.toISOString(),
        endAt: endAt.toISOString(),
        notes: notes.trim() || null,
      }),
    })

    const payload = (await response.json().catch(() => null)) as { error?: string } | null

    if (!response.ok) {
      setError(payload?.error ?? "No se pudo guardar la reserva")
      setSubmitting(false)
      return
    }

    toast.success(mode === "edit" ? "Reserva actualizada" : "Reserva creada")
    setSubmitting(false)
    onSaved()
    onClose()
  }

  return (
    <Dialog open={open} onOpenChange={(next) => !next && onClose()}>
      <DialogContent className="sm:max-w-[560px] rounded-[var(--ds-radius-l)] border-[var(--ds-neutral-200)] bg-white shadow-[var(--ds-shadow-8dp)]">
        <DialogHeader>
          <DialogTitle className="ds-type-global-m ds-type-semibold text-[var(--ds-text-neutral-default)]">
            {mode === "edit" ? "Editar reserva" : "Pedir de nuevo"}
          </DialogTitle>
          <DialogDescription className="ds-type-global-xs text-[var(--ds-text-neutral-lighter)]">
            {mode === "edit"
              ? "Puedes cambiar recurso, fecha, hora, duración y notas."
              : "Creamos una nueva reserva prellenada para que ajustes lo necesario."}
          </DialogDescription>
        </DialogHeader>

        <form onSubmit={handleSubmit}>
          <FieldGroup className="gap-[var(--ds-space-2x)] py-[var(--ds-space-2x)]">
            <Field>
              <FieldLabel>Recurso</FieldLabel>
              <Select value={resourceId} onValueChange={setResourceId} disabled={loadingResources}>
                <SelectTrigger className="rounded-[var(--ds-radius-m)] border-[var(--ds-neutral-300)]">
                  <SelectValue placeholder="Selecciona recurso" />
                </SelectTrigger>
                <SelectContent>
                  {resources.map((resource) => (
                    <SelectItem key={resource.id} value={resource.id}>
                      {resource.name} • {getResourceLocationPathLabel(resource) ?? "Sin ubicacion jerarquica"}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </Field>

            <div className="grid grid-cols-1 gap-[var(--ds-space-2x)] md:grid-cols-2">
              <Field>
                <FieldLabel>Fecha</FieldLabel>
                <Popover>
                  <PopoverTrigger asChild>
                    <Button
                      type="button"
                      variant="outline"
                      className={cn(
                        "w-full justify-start rounded-[var(--ds-radius-m)] border-[var(--ds-neutral-300)] text-left ds-type-global-xs",
                      )}
                    >
                      <CalendarIcon className="mr-2 h-4 w-4" />
                      {format(selectedDate, "EEE d MMM yyyy", { locale: es })}
                    </Button>
                  </PopoverTrigger>
                  <PopoverContent className="w-auto p-0" align="start">
                    <Calendar
                      mode="single"
                      selected={selectedDate}
                      onSelect={(date) => date && setSelectedDate(date)}
                      disabled={(date) => isBefore(startOfDay(date), startOfDay(new Date()))}
                      locale={es}
                    />
                  </PopoverContent>
                </Popover>
              </Field>

              <Field>
                <FieldLabel>Hora de inicio</FieldLabel>
                <Select value={startTime} onValueChange={setStartTime}>
                  <SelectTrigger className="rounded-[var(--ds-radius-m)] border-[var(--ds-neutral-300)]">
                    <SelectValue />
                  </SelectTrigger>
                  <SelectContent>
                    {slotOptions.map((slot) => (
                      <SelectItem key={slot} value={slot}>
                        {slot}
                      </SelectItem>
                    ))}
                  </SelectContent>
                </Select>
              </Field>
            </div>

            <Field>
              <FieldLabel>Duración</FieldLabel>
              <Select value={duration.toString()} onValueChange={(v) => setDuration(parseInt(v, 10))}>
                <SelectTrigger className="rounded-[var(--ds-radius-m)] border-[var(--ds-neutral-300)]">
                  <SelectValue />
                </SelectTrigger>
                <SelectContent>
                  {durationOptions.map((item) => (
                    <SelectItem key={item} value={item.toString()}>
                      {formatDurationLabel(item)}
                    </SelectItem>
                  ))}
                </SelectContent>
              </Select>
            </Field>

            <Field>
              <FieldLabel>Notas</FieldLabel>
              <Textarea
                value={notes}
                onChange={(e) => setNotes(e.target.value)}
                rows={3}
                className="rounded-[var(--ds-radius-m)] border-[var(--ds-neutral-300)]"
              />
            </Field>

            {error && <p className="ds-type-global-xs text-[var(--ds-error-700)]">{error}</p>}
          </FieldGroup>

          <DialogFooter>
            <Button type="button" variant="outline" onClick={onClose}>
              Cancelar
            </Button>
            <Button
              type="submit"
              disabled={submitting || durationOptions.length === 0}
              className="rounded-[var(--ds-radius-m)] bg-[var(--ds-brand-400)] text-white hover:bg-[var(--ds-brand-500)]"
            >
              {submitting && <Spinner className="mr-2" />}
              {mode === "edit" ? "Guardar cambios" : "Crear reserva"}
            </Button>
          </DialogFooter>
        </form>
      </DialogContent>
    </Dialog>
  )
}
