"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import type { LeaveStatus, LeaveType } from "@prisma/client";
import { Badge } from "@/components/ui/badge";
import { AdminDialog } from "@/components/ui/admin-dialog";
import { applyLeave, decideLeave } from "./actions";

const INPUT = "w-full rounded-lg border border-neutral-300 px-3 py-2 text-sm focus:border-primary-500 focus:outline-none focus:ring-2 focus:ring-primary-500/20";
const LEAVE_TYPES: LeaveType[] = ["ANNUAL", "MEDICAL", "EMERGENCY", "UNPAID", "OTHER"];
const fmt = (iso: string) => new Date(iso).toLocaleDateString();
const label = (s: string) => s.replace(/_/g, " ").toLowerCase().replace(/\b\w/g, (m) => m.toUpperCase());

type Assignment = { id: string; crewName: string; rank: string; location: string };
type Request = { id: string; crewName: string; rank: string; location: string; type: LeaveType; status: LeaveStatus; fromDate: string; toDate: string; reason: string | null };

const STATUS_VARIANT: Record<LeaveStatus, "warning" | "success" | "danger" | "secondary"> = {
  APPLIED: "warning", APPROVED: "success", REJECTED: "danger", CANCELLED: "secondary",
};

export function LeaveManager({ assignments, requests, canApply, canDecide }: { assignments: Assignment[]; requests: Request[]; canApply: boolean; canDecide: boolean }) {
  const router = useRouter();
  const [open, setOpen] = useState(false);
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");
  const [f, setF] = useState({ assignmentId: "", type: "ANNUAL", fromDate: "", toDate: "", reason: "" });

  const duration = f.fromDate && f.toDate ? Math.max(0, Math.round((new Date(f.toDate).getTime() - new Date(f.fromDate).getTime()) / 86400000) + 1) : 0;

  async function submitApply(e: React.FormEvent) {
    e.preventDefault();
    setPending(true); setError("");
    const fd = new FormData();
    Object.entries(f).forEach(([k, v]) => v && fd.set(k, v));
    const res = await applyLeave(fd);
    setPending(false);
    if ("error" in res) setError(res.error);
    else { setOpen(false); setF({ assignmentId: "", type: "ANNUAL", fromDate: "", toDate: "", reason: "" }); router.refresh(); }
  }

  return (
    <div>
      <div className="mb-6 flex items-center justify-between">
        <div>
          <h1 className="text-2xl font-semibold text-neutral-900">Leave</h1>
          <p className="text-sm text-neutral-500 mt-0.5">Site staff apply on behalf of crew · the Manager approves.</p>
        </div>
        {canApply && <button onClick={() => setOpen(true)} className="rounded-lg bg-primary-600 px-4 py-2.5 text-sm font-semibold text-white hover:bg-primary-700">Apply for leave</button>}
      </div>

      <div className="rounded-lg border border-neutral-200 bg-white overflow-hidden">
        <table className="w-full text-sm">
          <thead>
            <tr className="border-b border-neutral-200 bg-neutral-50 text-left text-xs font-semibold text-neutral-500 uppercase tracking-wide">
              <th className="px-4 py-3">Crew</th>
              <th className="px-4 py-3">Rank / location</th>
              <th className="px-4 py-3">Type</th>
              <th className="px-4 py-3">Dates</th>
              <th className="px-4 py-3">Status</th>
              <th className="px-4 py-3"></th>
            </tr>
          </thead>
          <tbody>
            {requests.length === 0 ? (
              <tr><td colSpan={6} className="px-4 py-12 text-center text-neutral-400">No leave requests.</td></tr>
            ) : requests.map((r) => (
              <DecisionRow key={r.id} r={r} canDecide={canDecide} onDone={() => router.refresh()} />
            ))}
          </tbody>
        </table>
      </div>

      <AdminDialog title="Apply for leave" open={open} onClose={() => setOpen(false)}>
        <form onSubmit={submitApply} className="space-y-4">
          <div>
            <label className="block text-xs font-medium text-neutral-700 mb-1">Crew member *</label>
            <select className={INPUT} value={f.assignmentId} onChange={(e) => setF({ ...f, assignmentId: e.target.value })} required>
              <option value="">— Select crew —</option>
              {assignments.map((a) => <option key={a.id} value={a.id}>{a.crewName} · {a.rank} · {a.location}</option>)}
            </select>
          </div>
          <div className="grid grid-cols-2 gap-3">
            <div>
              <label className="block text-xs font-medium text-neutral-700 mb-1">Type</label>
              <select className={INPUT} value={f.type} onChange={(e) => setF({ ...f, type: e.target.value })}>
                {LEAVE_TYPES.map((t) => <option key={t} value={t}>{label(t)}</option>)}
              </select>
            </div>
            <div></div>
            <div>
              <label className="block text-xs font-medium text-neutral-700 mb-1">From *</label>
              <input type="date" className={INPUT} value={f.fromDate} onChange={(e) => setF({ ...f, fromDate: e.target.value })} required />
            </div>
            <div>
              <label className="block text-xs font-medium text-neutral-700 mb-1">To *</label>
              <input type="date" className={INPUT} value={f.toDate} onChange={(e) => setF({ ...f, toDate: e.target.value })} required />
            </div>
          </div>
          {duration > 0 && <p className="text-xs text-neutral-500 bg-neutral-50 rounded-md px-3 py-2">{duration} day{duration === 1 ? "" : "s"} of leave.</p>}
          <div>
            <label className="block text-xs font-medium text-neutral-700 mb-1">Reason</label>
            <input className={INPUT} value={f.reason} onChange={(e) => setF({ ...f, reason: e.target.value })} placeholder="Optional" />
          </div>
          {error && <p className="text-sm text-danger-700 bg-danger-50 rounded-lg px-3 py-2">{error}</p>}
          <div className="flex justify-end gap-3">
            <button type="button" className="rounded-lg border border-neutral-300 px-4 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-50" onClick={() => setOpen(false)}>Cancel</button>
            <button type="submit" disabled={pending || !f.assignmentId} className="rounded-lg bg-primary-600 px-4 py-2 text-sm font-semibold text-white hover:bg-primary-700 disabled:opacity-60">{pending ? "Applying…" : "Apply"}</button>
          </div>
        </form>
      </AdminDialog>
    </div>
  );
}

function DecisionRow({ r, canDecide, onDone }: { r: Request; canDecide: boolean; onDone: () => void }) {
  const [pending, setPending] = useState(false);
  const [error, setError] = useState("");
  const [declineOpen, setDeclineOpen] = useState(false);
  const [reason, setReason] = useState("");

  async function approve() {
    setPending(true); setError("");
    const res = await decideLeave(r.id, true);
    setPending(false);
    if ("error" in res) setError(res.error); else onDone();
  }
  async function decline(e: React.FormEvent) {
    e.preventDefault();
    setPending(true); setError("");
    const res = await decideLeave(r.id, false, reason);
    setPending(false);
    if ("error" in res) setError(res.error); else { setDeclineOpen(false); onDone(); }
  }

  return (
    <tr className="border-b border-neutral-100 last:border-0 hover:bg-neutral-50">
      <td className="px-4 py-3 font-medium text-neutral-900">{r.crewName}</td>
      <td className="px-4 py-3 text-neutral-600">{r.rank} · {r.location}</td>
      <td className="px-4 py-3 text-neutral-600">{label(r.type)}</td>
      <td className="px-4 py-3 text-neutral-600">{fmt(r.fromDate)} – {fmt(r.toDate)}</td>
      <td className="px-4 py-3"><Badge variant={STATUS_VARIANT[r.status]}>{label(r.status)}</Badge></td>
      <td className="px-4 py-3 text-right">
        {r.status === "APPLIED" && (canDecide ? (
          <div className="flex justify-end gap-2">
            <button onClick={approve} disabled={pending} className="rounded-md bg-primary-600 px-3 py-1.5 text-xs font-semibold text-white hover:bg-primary-700 disabled:opacity-60">Approve</button>
            <button onClick={() => setDeclineOpen(true)} disabled={pending} className="rounded-md border border-neutral-300 px-3 py-1.5 text-xs font-medium text-neutral-700 hover:bg-neutral-50">Decline</button>
          </div>
        ) : <span className="text-xs text-neutral-400">Awaiting manager</span>)}
        {error && <p className="text-xs text-danger-700 mt-1">{error}</p>}
        <AdminDialog title="Decline leave" open={declineOpen} onClose={() => setDeclineOpen(false)}>
          <form onSubmit={decline} className="space-y-4 text-left">
            <textarea className={INPUT} rows={3} value={reason} onChange={(e) => setReason(e.target.value)} required placeholder="Reason" />
            <div className="flex justify-end gap-3">
              <button type="button" className="rounded-lg border border-neutral-300 px-4 py-2 text-sm font-medium text-neutral-700 hover:bg-neutral-50" onClick={() => setDeclineOpen(false)}>Cancel</button>
              <button type="submit" disabled={pending} className="rounded-lg bg-primary-600 px-4 py-2 text-sm font-semibold text-white hover:bg-primary-700 disabled:opacity-60">Decline</button>
            </div>
          </form>
        </AdminDialog>
      </td>
    </tr>
  );
}
