"use client"

import { useState, useMemo, useEffect } from "react"
import { useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Dropdown } from "@/components/ui/dropdown"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"

type Option = { id: string; name: string }
type EmployeeOption = {
  id: string
  name: string
  branchId?: string
  departmentId?: string
  subDepartmentId?: string
}
type PublicHoliday = { date: string; endDate?: string | null }

function toDateInputValue(d?: Date | string | null) {
  if (!d) return ""
  const date = d instanceof Date ? d : new Date(d)
  if (Number.isNaN(date.getTime())) return ""
  return date.toISOString().slice(0, 10)
}

function getDatesInRange(start: string, end: string): Date[] {
  const dates: Date[] = []
  if (!start || !end) return dates
  const current = new Date(start)
  const endDate = new Date(end)
  while (current <= endDate) {
    dates.push(new Date(current))
    current.setDate(current.getDate() + 1)
  }
  return dates
}

function isFriday(date: Date): boolean { return date.getDay() === 5 }

function isPublicHoliday(date: Date, holidays: PublicHoliday[]): boolean {
  return holidays.some((h) => {
    const hStart = new Date(h.date)
    const hEnd = h.endDate ? new Date(h.endDate) : new Date(h.date)
    hStart.setHours(0, 0, 0, 0)
    hEnd.setHours(23, 59, 59, 999)
    return date >= hStart && date <= hEnd
  })
}

function calculateDuration(
  start: string, end: string,
  excludeFridays: boolean, excludeHolidays: boolean,
  holidays: PublicHoliday[]
): { total: number; excluded: number; net: number } {
  const dates = getDatesInRange(start, end)
  if (!dates.length) return { total: 0, excluded: 0, net: 0 }
  let excluded = 0
  dates.forEach((d) => {
    if (excludeFridays && isFriday(d)) excluded++
    else if (excludeHolidays && isPublicHoliday(d, holidays)) excluded++
  })
  return { total: dates.length, excluded, net: dates.length - excluded }
}

type LeaveRequestFormProps = {
  initialData?: {
    id?: string
    employeeId?: string
    leaveTypeId?: string
    startDate?: Date | string
    endDate?: Date | string
    reason?: string
  }
  employees: EmployeeOption[]
  leaveTypes: Option[]
  branches: Option[]
  publicHolidays: PublicHoliday[]
}

export default function LeaveRequestForm({
  initialData,
  employees,
  leaveTypes,
  branches,
  publicHolidays,
}: LeaveRequestFormProps) {
  const router = useRouter()
  const isEdit = Boolean(initialData?.id)

  // ── Branch → Department → SubDepartment cascade ───────────────────────────
  const [branchFilter,   setBranchFilter]   = useState("")
  const [deptFilter,     setDeptFilter]     = useState("")
  const [subDeptFilter,  setSubDeptFilter]  = useState("")

  const [departments,    setDepartments]    = useState<Option[]>([])
  const [subDepartments, setSubDepartments] = useState<Option[]>([])
  const [depsLoading,    setDepsLoading]    = useState(false)
  const [subDepsLoading, setSubDepsLoading] = useState(false)

  // Fetch departments when branch changes
  useEffect(() => {
    if (!branchFilter) {
      setDepartments([])
      setDeptFilter("")
      setSubDepartments([])
      setSubDeptFilter("")
      return
    }
    setDepsLoading(true)
    setDeptFilter("")
    setSubDepartments([])
    setSubDeptFilter("")
    fetch(`/api/departments?branchId=${branchFilter}`)
      .then(r => r.json())
      .then(setDepartments)
      .catch(() => setDepartments([]))
      .finally(() => setDepsLoading(false))
  }, [branchFilter])

  // Fetch sub-departments when department changes
  useEffect(() => {
    if (!deptFilter) {
      setSubDepartments([])
      setSubDeptFilter("")
      return
    }
    setSubDepsLoading(true)
    setSubDeptFilter("")
    fetch(`/api/departments?departmentId=${deptFilter}`)
      .then(r => r.json())
      .then(setSubDepartments)
      .catch(() => setSubDepartments([]))
      .finally(() => setSubDepsLoading(false))
  }, [deptFilter])

  // ── Core fields ───────────────────────────────────────────────────────────
  const [employeeId,  setEmployeeId]  = useState(initialData?.employeeId  || "")
  const [leaveTypeId, setLeaveTypeId] = useState(initialData?.leaveTypeId || "")
  const [startDate,   setStartDate]   = useState(toDateInputValue(initialData?.startDate))
  const [endDate,     setEndDate]     = useState(toDateInputValue(initialData?.endDate))
  const [reason,      setReason]      = useState(initialData?.reason || "")
  const [excludeFridays,  setExcludeFridays]  = useState(true)
  const [excludeHolidays, setExcludeHolidays] = useState(true)
  const [loading, setLoading] = useState(false)
  const [error,   setError]   = useState("")

  const [leaveBalance, setLeaveBalance] = useState<{
    totalDays: number; usedDays: number; remainingDays: number
    allowanceExists: boolean; loading: boolean
  }>({ totalDays: 0, usedDays: 0, remainingDays: 0, allowanceExists: false, loading: false })

  // ── Filtered employees ────────────────────────────────────────────────────
  const filteredEmployees = useMemo(() => employees.filter((e) => {
    if (branchFilter  && e.branchId       !== branchFilter)  return false
    if (deptFilter    && e.departmentId   !== deptFilter)    return false
    if (subDeptFilter && e.subDepartmentId !== subDeptFilter) return false
    return true
  }), [employees, branchFilter, deptFilter, subDeptFilter])

  // Clear selected employee if they no longer appear in the filtered list
  useEffect(() => {
    if (employeeId && !filteredEmployees.find(e => e.id === employeeId)) {
      setEmployeeId("")
    }
  }, [filteredEmployees, employeeId])

  // ── Duration ──────────────────────────────────────────────────────────────
  const duration = useMemo(
    () => calculateDuration(startDate, endDate, excludeFridays, excludeHolidays, publicHolidays),
    [startDate, endDate, excludeFridays, excludeHolidays, publicHolidays]
  )

  // ── Leave balance ─────────────────────────────────────────────────────────
  useEffect(() => {
    if (!employeeId || !leaveTypeId) {
      setLeaveBalance({ totalDays: 0, usedDays: 0, remainingDays: 0, allowanceExists: false, loading: false })
      return
    }
    let cancelled = false
    setLeaveBalance(p => ({ ...p, loading: true }))
    fetch(`/api/leave-balance?employeeId=${employeeId}&leaveTypeId=${leaveTypeId}`)
      .then(r => r.json())
      .then(data => { if (!cancelled) setLeaveBalance({ ...data, loading: false }) })
      .catch(() => { if (!cancelled) setLeaveBalance({ totalDays: 0, usedDays: 0, remainingDays: 0, allowanceExists: false, loading: false }) })
    return () => { cancelled = true }
  }, [employeeId, leaveTypeId])

  const canSubmit = duration.net > 0 && (leaveBalance.allowanceExists ? duration.net <= leaveBalance.remainingDays : true)

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault()
    setLoading(true)
    setError("")
    try {
      const body = {
        employeeId, leaveTypeId,
        startDate:  startDate ? new Date(startDate) : undefined,
        endDate:    endDate   ? new Date(endDate)   : undefined,
        duration:   duration.net,
        reason:     reason || undefined,
        excludeFridays, excludeHolidays,
      }
      const id  = initialData?.id
      const url = id ? `/api/leave-requests/${id}` : "/api/leave-requests"
      const res = await fetch(url, { method: id ? "PUT" : "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) })
      if (!res.ok) {
        const data = await res.json().catch(() => null)
        throw new Error(data?.error || "Failed to save leave request")
      }
      router.push("/leave")
      router.refresh()
    } catch (err) {
      setError(err instanceof Error ? err.message : "Failed to save leave request")
    } finally {
      setLoading(false)
    }
  }

  // ── Dropdown option lists ─────────────────────────────────────────────────
  const branchOptions   = branches.map(b => ({ value: b.id, label: b.name }))
  const deptOptions     = departments.map(d => ({ value: d.id, label: d.name }))
  const subDeptOptions  = subDepartments.map(s => ({ value: s.id, label: s.name }))
  const employeeOptions = filteredEmployees.map(e => ({ value: e.id, label: e.name }))
  const leaveTypeOptions = leaveTypes.map(t => ({ value: t.id, label: t.name }))

  return (
    <form onSubmit={handleSubmit} className="space-y-6">
      {error && (
        <div className="rounded-md border border-red-200 bg-red-50 p-3 text-sm text-red-600">{error}</div>
      )}

      <Card>
        <CardHeader>
          <CardTitle className="text-base">Leave Request Details</CardTitle>
        </CardHeader>
        <CardContent className="space-y-6">

          {/* ── Branch → Department → SubDepartment → Employee ── */}
          <div className="space-y-3">
            <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">Select Employee</p>

            {/* Row 1: Branch + Department + SubDepartment */}
            <div className="grid gap-4 md:grid-cols-3">
              <Dropdown
                label="Company"
                placeholder="All Companies"
                searchPlaceholder="Search companies…"
                options={branchOptions}
                value={branchFilter}
                onChange={setBranchFilter}
                clearable
              />

              <div>
                <Dropdown
                  label={depsLoading ? "Department (loading…)" : "Department"}
                  placeholder="All departments"
                  searchPlaceholder="Search departments…"
                  options={deptOptions}
                  value={deptFilter}
                  onChange={setDeptFilter}
                  disabled={!branchFilter || depsLoading}
                  clearable
                />
                {branchFilter && !depsLoading && departments.length === 0 && (
                  <p className="text-xs text-muted-foreground mt-1">No departments for this branch.</p>
                )}
              </div>

              <div>
                <Dropdown
                  label={subDepsLoading ? "Sub-department (loading…)" : "Sub-department"}
                  placeholder="All sub-departments"
                  searchPlaceholder="Search sub-departments…"
                  options={subDeptOptions}
                  value={subDeptFilter}
                  onChange={setSubDeptFilter}
                  disabled={!deptFilter || subDepsLoading}
                  clearable
                />
                {deptFilter && !subDepsLoading && subDepartments.length === 0 && (
                  <p className="text-xs text-muted-foreground mt-1">No sub-departments for this department.</p>
                )}
              </div>
            </div>

            {/* Row 2: Employee (full width on its own row so it's prominent) */}
            <div className="grid gap-4 md:grid-cols-3">
              <div className="md:col-span-3">
                <Dropdown
                  label={`Employee${filteredEmployees.length ? ` (${filteredEmployees.length})` : ""} *`}
                  placeholder="Select employee…"
                  searchPlaceholder="Search by name…"
                  options={employeeOptions}
                  value={employeeId}
                  onChange={setEmployeeId}
                  emptyMessage="No employees match the filters."
                />
              </div>
            </div>
          </div>

          <div className="border-t border-border" />

          {/* ── Leave Type + Dates ── */}
          <div className="grid gap-4 md:grid-cols-3">
            <Dropdown
              label="Leave Type *"
              placeholder="Select leave type…"
              searchPlaceholder="Search leave types…"
              options={leaveTypeOptions}
              value={leaveTypeId}
              onChange={setLeaveTypeId}
            />

            <div className="space-y-1.5">
              <Label>Start Date</Label>
              <Input type="date" value={startDate} onChange={e => setStartDate(e.target.value)} required />
            </div>

            <div className="space-y-1.5">
              <Label>End Date</Label>
              <Input type="date" value={endDate} onChange={e => setEndDate(e.target.value)} required />
            </div>
          </div>

          {/* ── Day Counting Options ── */}
          <div className="space-y-3">
            <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">Day Counting Options</p>
            <div className="flex flex-wrap gap-4">
              <label className="flex items-center gap-2 text-sm cursor-pointer">
                <input type="checkbox" className="h-4 w-4 rounded" checked={excludeFridays} onChange={e => setExcludeFridays(e.target.checked)} />
                Exclude Fridays (weekends)
              </label>
              <label className="flex items-center gap-2 text-sm cursor-pointer">
                <input type="checkbox" className="h-4 w-4 rounded" checked={excludeHolidays} onChange={e => setExcludeHolidays(e.target.checked)} />
                Exclude Public Holidays
              </label>
            </div>
          </div>

          {/* ── Duration Breakdown ── */}
          {startDate && endDate && (
            <div className="rounded-lg border border-border bg-muted/30 p-4 space-y-2">
              <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">Duration Breakdown</p>
              <div className="grid grid-cols-3 gap-4 text-center">
                <div>
                  <p className="text-2xl font-bold">{duration.total}</p>
                  <p className="text-xs text-muted-foreground">Calendar days</p>
                </div>
                <div>
                  <p className="text-2xl font-bold text-amber-500">−{duration.excluded}</p>
                  <p className="text-xs text-muted-foreground">Excluded</p>
                </div>
                <div>
                  <p className="text-2xl font-bold text-emerald-600">{duration.net}</p>
                  <p className="text-xs text-muted-foreground">Leave days</p>
                </div>
              </div>
              {duration.excluded > 0 && (
                <p className="text-xs text-muted-foreground text-center">
                  {excludeFridays && excludeHolidays ? "Fridays & public holidays excluded" :
                   excludeFridays ? "Fridays excluded" : "Public holidays excluded"}
                </p>
              )}
            </div>
          )}

          {/* ── Leave Balance ── */}
          {employeeId && leaveTypeId && (
            <div className="space-y-2">
              <p className="text-xs font-semibold uppercase tracking-widest text-muted-foreground">Leave Balance</p>
              <div className={`rounded-md border px-4 py-3 text-sm ${
                leaveBalance.loading           ? "border-input bg-muted/50" :
                !leaveBalance.allowanceExists  ? "border-amber-300 bg-amber-50 text-amber-800" :
                duration.net > leaveBalance.remainingDays ? "border-red-300 bg-red-50 text-red-800" :
                "border-emerald-300 bg-emerald-50 text-emerald-800"
              }`}>
                {leaveBalance.loading ? "Loading balance…" :
                !leaveBalance.allowanceExists ? "No leave allowance configured for this employee and leave type." : (
                  <div className="flex flex-wrap gap-x-6 gap-y-1">
                    <span>Total: <strong>{leaveBalance.totalDays}</strong> days</span>
                    <span>Used: <strong>{leaveBalance.usedDays}</strong> days</span>
                    <span>Remaining: <strong>{leaveBalance.remainingDays}</strong> days</span>
                    {duration.net > 0 && (
                      <span className="w-full text-xs mt-1">
                        After this request: <strong>{Math.max(0, leaveBalance.remainingDays - duration.net)}</strong> days remaining
                        {duration.net > leaveBalance.remainingDays && (
                          <span className="ml-2 text-red-600 font-semibold">
                            ⚠ Insufficient! Needs {duration.net}, only {leaveBalance.remainingDays} available.
                          </span>
                        )}
                      </span>
                    )}
                  </div>
                )}
              </div>
            </div>
          )}

          {/* ── Reason ── */}
          <div className="space-y-1.5">
            <Label>Reason <span className="text-muted-foreground text-xs">(optional)</span></Label>
            <Input value={reason} onChange={e => setReason(e.target.value)} placeholder="Enter reason for leave" />
          </div>

        </CardContent>
      </Card>

      <div className="flex items-center justify-end gap-3">
        <Button type="button" variant="outline" onClick={() => router.push("/leave")}>Cancel</Button>
        <Button type="submit" disabled={loading || !canSubmit}>
          {loading ? (isEdit ? "Updating…" : "Creating…") : isEdit ? "Update Request" : "Create Request"}
        </Button>
      </div>
    </form>
  )
}