"use client"

import { useState, useCallback } from "react"
import { useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Card, CardContent } from "@/components/ui/card"
import {
  Dialog, DialogContent, DialogDescription,
  DialogFooter, DialogHeader, DialogTitle,
} from "@/components/ui/dialog"
import { Dropdown } from "@/components/ui/dropdown"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Badge } from "@/components/ui/badge"


export type PublicHoliday = {
  id: string; name: string; date: string; endDate?: string
  type: "public_holiday" | "company_holiday" | "optional_holiday"; description?: string
}

type Props = { holidays: PublicHoliday[]; canManage?: boolean }

const DAYS = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
const MONTHS = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
const HOLIDAY_TYPES = [
  { value: "public_holiday", label: "Public Holiday" },
  { value: "company_holiday", label: "Company Holiday" },
  { value: "optional_holiday", label: "Optional Holiday" },
]
const C: Record<string, { badge: string; bg: string; text: string; border: string; dot: string }> = {
  public_holiday: { badge: "bg-red-100 text-red-800 border-red-200", bg: "#fee2e2", text: "#b91c1c", border: "#fca5a5", dot: "#ef4444" },
  company_holiday: { badge: "bg-blue-100 text-blue-800 border-blue-200", bg: "#dbeafe", text: "#1d4ed8", border: "#93c5fd", dot: "#3b82f6" },
  optional_holiday: { badge: "bg-amber-100 text-amber-800 border-amber-200", bg: "#fef3c7", text: "#b45309", border: "#fcd34d", dot: "#f59e0b" },
}
const FRI = 5

function toISO(d: Date) { return d.toISOString().split("T")[0] }
function parseISO(s: string) { const [y, m, d] = s.split("-").map(Number); return new Date(y, m - 1, d) }
function holidayFor(iso: string, holidays: PublicHoliday[]) {
  const d = parseISO(iso)
  return holidays.find(h => { const s = parseISO(h.date), e = h.endDate ? parseISO(h.endDate) : s; return d >= s && d <= e })
}

function MonthGrid({ year, month, holidays, todayISO, selectionStart, selectionEnd, isDragging, onMouseDown, onMouseEnter, onMouseUp, canManage }: {
  year: number; month: number; holidays: PublicHoliday[]; todayISO: string
  selectionStart: string | null; selectionEnd: string | null; isDragging: boolean
  onMouseDown: (iso: string) => void; onMouseEnter: (iso: string) => void; onMouseUp: (iso: string) => void; canManage: boolean
}) {
  const firstDay = new Date(year, month, 1)
  const lastDay = new Date(year, month + 1, 0)
  const offset = firstDay.getDay()
  const cells: (number | null)[] = [...Array(offset).fill(null), ...Array.from({ length: lastDay.getDate() }, (_, i) => i + 1)]
  const selA = selectionStart && selectionEnd ? [selectionStart, selectionEnd].sort()[0] : selectionStart
  const selB = selectionStart && selectionEnd ? [selectionStart, selectionEnd].sort()[1] : selectionStart

  return (
    <div style={{ userSelect: "none", width: "100%" }}>
      {/* Day labels */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", marginBottom: "3px" }}>
        {DAYS.map((d, i) => (
          <div key={d} style={{ textAlign: "center", fontSize: "9px", fontWeight: 700, padding: "2px 0", color: i === FRI ? "#3b82f6" : "#9ca3af", letterSpacing: "0.02em" }}>
            {d}
          </div>
        ))}
      </div>
      {/* Cells */}
      <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: "2px" }}>
        {cells.map((day, idx) => {
          if (day === null) return (
            <div key={`p${idx}`} style={{ position: "relative", width: "100%", paddingBottom: "100%" }} />
          )
          const iso = `${year}-${String(month + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`
          const holiday = holidayFor(iso, holidays)
          const isToday = iso === todayISO
          const isFri = new Date(year, month, day).getDay() === FRI
          const inSel = isDragging && selA && selB && iso >= selA && iso <= selB
          const col = holiday ? C[holiday.type] : null

          let bg = "#ffffff", border = "#e5e7eb", color = "#374151", fw = 400
          if (inSel) { bg = "#bfdbfe"; border = "#60a5fa"; color = "#1e40af"; fw = 600 }
          else if (col) { bg = col.bg; border = col.border; color = col.text; fw = 600 }
          else if (isToday) { bg = "#fef9c3"; border = "#fde047"; color = "#854d0e"; fw = 700 }
          else if (isFri) { bg = "#eff6ff"; border = "#bfdbfe"; color = "#2563eb"; fw = 500 }

          return (
            <div key={iso} style={{ position: "relative", width: "100%", paddingBottom: "100%" }}>
              <div
                style={{
                  position: "absolute", inset: "0",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  fontSize: "11px", fontWeight: fw,
                  borderRadius: "4px", border: `1px solid ${border}`,
                  background: bg, color,
                  cursor: canManage ? "pointer" : "default",
                  transition: "opacity 0.1s",
                }}
                onMouseDown={() => canManage && onMouseDown(iso)}
                onMouseEnter={() => canManage && onMouseEnter(iso)}
                onMouseUp={() => canManage && onMouseUp(iso)}
                title={holiday?.name}
              >
                {day}
                {holiday && (
                  <span style={{
                    position: "absolute", bottom: "2px", left: "50%", transform: "translateX(-50%)",
                    width: "3px", height: "3px", borderRadius: "50%", background: col?.dot,
                  }} />
                )}
              </div>
            </div>
          )
        })}
      </div>
    </div>
  )
}

function HolidayList({ holidays, year, onEdit, canManage }: {
  holidays: PublicHoliday[]; year: number; onEdit: (h: PublicHoliday) => void; canManage: boolean
}) {
  const list = holidays.filter(h => h.date.startsWith(String(year))).sort((a, b) => a.date.localeCompare(b.date))
  if (!list.length) return <p className="text-sm text-muted-foreground py-4 text-center">No holidays for {year}.</p>
  return (
    <div className="space-y-2">
      {list.map(h => {
        const s = parseISO(h.date), e = h.endDate ? parseISO(h.endDate) : s
        const days = Math.round((e.getTime() - s.getTime()) / 86400000) + 1
        return (
          <div key={h.id} onClick={() => canManage && onEdit(h)}
            className={`flex items-start gap-2 p-2 rounded-lg border text-sm ${canManage ? "cursor-pointer hover:bg-muted/50" : ""}`}>
            <div className="flex-1 min-w-0">
              <p className="font-medium truncate text-xs">{h.name}</p>
              <p className="text-[10px] text-muted-foreground">
                {s.toLocaleDateString("en-GB", { day: "numeric", month: "short" })}
                {days > 1 && ` → ${e.toLocaleDateString("en-GB", { day: "numeric", month: "short" })} (${days}d)`}
              </p>
            </div>
            <Badge variant="outline" className={`text-[10px] shrink-0 ${C[h.type]?.badge}`}>
              {HOLIDAY_TYPES.find(t => t.value === h.type)?.label ?? h.type}
            </Badge>
          </div>
        )
      })}
    </div>
  )
}

type DM = "add" | "edit" | null
type HF = { name: string; type: PublicHoliday["type"]; description: string }

// Holiday type options for Dropdown
const HOLIDAY_TYPE_OPTIONS = HOLIDAY_TYPES.map(t => ({ value: t.value, label: t.label }))

function HolidayDialog({ open, mode, selectedDates, existing, onClose, onSave, onDelete }: {
  open: boolean; mode: DM; selectedDates: { start: string; end: string } | null; existing: PublicHoliday | null
  onClose: () => void; onSave: (f: HF) => Promise<void>; onDelete: () => Promise<void>
}) {
  const [form, setForm] = useState<HF>({ name: existing?.name ?? "", type: existing?.type ?? "public_holiday", description: existing?.description ?? "" })
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState("")
  const fmt = selectedDates
    ? selectedDates.start === selectedDates.end
      ? parseISO(selectedDates.start).toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric", year: "numeric" })
      : `${parseISO(selectedDates.start).toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric" })} → ${parseISO(selectedDates.end).toLocaleDateString("en-US", { weekday: "short", month: "short", day: "numeric", year: "numeric" })}`
    : ""
  async function save() {
    if (!form.name.trim()) { setError("Name required"); return }
    setLoading(true); setError("")
    try { await onSave(form) } catch (e) { setError(e instanceof Error ? e.message : "Failed") } finally { setLoading(false) }
  }
  async function del() {
    setLoading(true); setError("")
    try { await onDelete() } catch (e) { setError(e instanceof Error ? e.message : "Failed") } finally { setLoading(false) }
  }
  return (
    <Dialog open={open} onOpenChange={v => !v && onClose()}>
      <DialogContent className="sm:max-w-md">
        <DialogHeader>
          <DialogTitle>{mode === "add" ? "Add Holiday" : "Edit Holiday"}</DialogTitle>
          <DialogDescription asChild>
            <div className="mt-1 px-3 py-2 rounded-md bg-blue-50 border-l-4 border-blue-400 text-sm text-blue-800 font-medium">
              <span className="text-blue-600 font-semibold">Selected: </span>{fmt}
            </div>
          </DialogDescription>
        </DialogHeader>
        <div className="space-y-4 py-2" key={existing?.id ?? "new"}>
          <div className="space-y-1.5">
            <Label htmlFor="hn">Holiday Name <span className="text-destructive">*</span></Label>
            <Input id="hn" placeholder="e.g., Eid Al-Fitr, New Year" defaultValue={existing?.name ?? ""} onChange={e => setForm(f => ({ ...f, name: e.target.value }))} />
          </div>
          <div className="space-y-1.5">
            <Label>Holiday Type</Label>
            <Dropdown
              placeholder="Select type…"
              searchPlaceholder="Search types…"
              options={HOLIDAY_TYPE_OPTIONS}
              value={form.type}
              onChange={(v) => setForm(f => ({ ...f, type: v as PublicHoliday["type"] }))}
            />
          </div>
          <div className="space-y-1.5">
            <Label htmlFor="hd">Description (Optional)</Label>
            <textarea id="hd" rows={3} placeholder="Additional details..." defaultValue={existing?.description ?? ""} onChange={e => setForm(f => ({ ...f, description: e.target.value }))} className="flex min-h-[72px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring resize-none" />
          </div>
          {error && <p className="text-sm text-destructive">{error}</p>}
        </div>
        <DialogFooter className="flex-row gap-2">
          {mode === "edit" && <Button variant="destructive" onClick={del} disabled={loading} className="mr-auto">Delete</Button>}
          <Button variant="outline" onClick={onClose} disabled={loading}>Cancel</Button>
          <Button variant="default" onClick={save} disabled={loading}>
            Save Holiday
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  )
}

export default function PublicHolidaysCalendar({ holidays: init, canManage = true }: Props) {
  const router = useRouter()
  const today = new Date()
  const todayISO = toISO(today)
  const [year, setYear] = useState(today.getFullYear())
  const [holidays, setHolidays] = useState<PublicHoliday[]>(init)
  const [dragStart, setDragStart] = useState<string | null>(null)
  const [dragEnd, setDragEnd] = useState<string | null>(null)
  const [isDragging, setIsDragging] = useState(false)
  const [dialogMode, setDialogMode] = useState<DM>(null)
  const [dialogDates, setDialogDates] = useState<{ start: string; end: string } | null>(null)
  const [editingHoliday, setEditingHoliday] = useState<PublicHoliday | null>(null)

  const onDown = useCallback((iso: string) => { setDragStart(iso); setDragEnd(iso); setIsDragging(true) }, [])
  const onEnter = useCallback((iso: string) => { if (isDragging) setDragEnd(iso) }, [isDragging])
  const onUp = useCallback((iso: string) => {
    if (!isDragging || !dragStart) return
    setIsDragging(false)
    const [s, e] = [dragStart, iso].sort()
    const ex = holidayFor(s, holidays)
    if (ex && s === e) { setEditingHoliday(ex); setDialogDates({ start: ex.date, end: ex.endDate ?? ex.date }); setDialogMode("edit") }
    else { setDialogDates({ start: s, end: e }); setDialogMode("add") }
    setDragStart(null); setDragEnd(null)
  }, [isDragging, dragStart, holidays])
  const onLeave = useCallback(() => { if (isDragging) { setIsDragging(false); setDragStart(null); setDragEnd(null) } }, [isDragging])

  const closeDialog = () => { setDialogMode(null); setEditingHoliday(null); setDialogDates(null) }

  async function handleSave(form: HF) {
    if (!dialogDates) return
    const body = { name: form.name, type: form.type, description: form.description || undefined, date: dialogDates.start, endDate: dialogDates.end !== dialogDates.start ? dialogDates.end : undefined }
    if (dialogMode === "add") {
      const res = await fetch("/api/calendar", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) })
      if (!res.ok) throw new Error((await res.json().catch(() => null))?.error ?? "Failed")
      const newHoliday = await res.json()
      setHolidays(p => [...p, newHoliday])
    } else if (dialogMode === "edit" && editingHoliday) {
      const res = await fetch(`/api/calendar/${editingHoliday.id}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) })
      if (!res.ok) throw new Error((await res.json().catch(() => null))?.error ?? "Failed")
      const updated = await res.json()
      setHolidays(p => p.map(h => h.id === updated.id ? updated : h))
    }
    closeDialog(); router.refresh()
  }

  async function handleDelete() {
    if (!editingHoliday) return
    const res = await fetch(`/api/calendar/${editingHoliday.id}`, { method: "DELETE" })
    if (!res.ok) throw new Error((await res.json().catch(() => null))?.error ?? "Failed")
    setHolidays(p => p.filter(h => h.id !== editingHoliday.id))
    closeDialog(); router.refresh()
  }

  const selA = dragStart && dragEnd ? [dragStart, dragEnd].sort()[0] : dragStart
  const selB = dragStart && dragEnd ? [dragStart, dragEnd].sort()[1] : dragStart

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="flex items-center justify-between">
        <h2 className="text-xl font-bold">{year}</h2>
        <div className="flex gap-2">
          <Button variant="outline" size="sm" onClick={() => setYear(y => y - 1)}>← Previous</Button>
          <Button variant="outline" size="sm" onClick={() => setYear(y => y + 1)}>Next →</Button>
        </div>
      </div>

      {/* Legend */}
      <div className="flex flex-wrap items-center gap-x-4 gap-y-1.5 py-2 px-3 rounded-lg bg-muted/40 border text-xs">
        {[
          { bg: "#fef9c3", border: "#fde047", label: "Today" },
          { bg: "#eff6ff", border: "#bfdbfe", label: "Friday (Off)" },
          ...HOLIDAY_TYPES.map(t => ({ bg: C[t.value].bg, border: C[t.value].border, label: t.label }))
        ].map(item => (
          <div key={item.label} className="flex items-center gap-1.5">
            <span style={{ display: "inline-block", width: 12, height: 12, borderRadius: 2, background: item.bg, border: `1px solid ${item.border}`, flexShrink: 0 }} />
            <span className="text-muted-foreground">{item.label}</span>
          </div>
        ))}
        {canManage && <span className="ml-auto text-muted-foreground italic">Click or drag to add a holiday</span>}
      </div>

      {/* Grid + Sidebar */}
      <div className="flex gap-4 items-start">
        <div className="flex-1 grid grid-cols-3 md:grid-cols-4 xl:grid-cols-6 gap-2" onMouseLeave={onLeave}>
          {MONTHS.map((name, idx) => (
            <Card key={name} className="overflow-hidden shadow-sm border">
              <CardContent className="p-2">
                <p style={{ textAlign: "center", fontSize: "11px", fontWeight: 700, marginBottom: "6px", color: "#111827" }}>{name}</p>
                <MonthGrid
                  year={year} month={idx} holidays={holidays} todayISO={todayISO}
                  selectionStart={selA} selectionEnd={selB} isDragging={isDragging}
                  onMouseDown={onDown} onMouseEnter={onEnter} onMouseUp={onUp} canManage={canManage}
                />
              </CardContent>
            </Card>
          ))}
        </div>

        <div className="w-56 shrink-0 hidden lg:block">
          <Card className="shadow-sm">
            <CardContent className="p-4">
              <div className="flex items-center justify-between mb-3">
                <h3 className="text-sm font-semibold">Holidays {year}</h3>
                <Badge variant="secondary" className="text-xs">{holidays.filter(h => h.date.startsWith(String(year))).length}</Badge>
              </div>
              <HolidayList holidays={holidays} year={year} onEdit={h => { setEditingHoliday(h); setDialogDates({ start: h.date, end: h.endDate ?? h.date }); setDialogMode("edit") }} canManage={canManage} />
            </CardContent>
          </Card>
        </div>
      </div>

      <HolidayDialog open={dialogMode !== null} mode={dialogMode} selectedDates={dialogDates}
        existing={editingHoliday} onClose={closeDialog} onSave={handleSave} onDelete={handleDelete} />
    </div>
  )
}