"use client";

import { useRef, useState } from "react";
import { useFocusTrap } from "~/hooks/useFocusTrap.js";
import { VacationType } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { DateInput } from "~/components/ui/DateInput.js";
import { useDebounce } from "~/hooks/useDebounce.js";
import { InfoTooltip } from "~/components/ui/InfoTooltip.js";
import { VACATION_TYPE_LABELS } from "~/lib/status-styles.js";

const VACATION_TYPES = Object.values(VacationType);

interface VacationModalProps {
  resourceId?: string;
  onClose: () => void;
  onSuccess: () => void;
}

function toDateInputValue(date: Date | string | null | undefined): string {
  if (!date) return "";
  const d = typeof date === "string" ? new Date(date) : date;
  const y = d.getFullYear();
  const m = String(d.getMonth() + 1).padStart(2, "0");
  const day = String(d.getDate()).padStart(2, "0");
  return `${y}-${m}-${day}`;
}

export function VacationModal({ resourceId: initialResourceId, onClose, onSuccess }: VacationModalProps) {
  const [resourceId, setResourceId] = useState(initialResourceId ?? "");
  const [type, setType] = useState<VacationType>(VacationType.ANNUAL);
  const [startDate, setStartDate] = useState("");
  const [endDate, setEndDate] = useState("");
  const [note, setNote] = useState("");
  const [isHalfDay, setIsHalfDay] = useState(false);
  const [halfDayPart, setHalfDayPart] = useState<"MORNING" | "AFTERNOON">("MORNING");
  const [serverError, setServerError] = useState<string | null>(null);

  const panelRef = useRef<HTMLDivElement>(null);
  useFocusTrap(panelRef, true);

  const debouncedStart = useDebounce(startDate, 400);
  const debouncedEnd = useDebounce(endDate, 400);

  const { data: resources } = trpc.resource.list.useQuery(
    { isActive: true, limit: 500 },
    { staleTime: 60_000 },
  );

  // Team overlap: other resources in same chapter off in this period
  const { data: teamOverlap } = trpc.vacation.getTeamOverlap.useQuery(
    {
      resourceId: resourceId,
      startDate: debouncedStart ? new Date(debouncedStart) : new Date(),
      endDate: debouncedEnd ? new Date(debouncedEnd) : new Date(),
    },
    {
      enabled: !!resourceId && !!debouncedStart && !!debouncedEnd,
      staleTime: 10_000,
    },
  );

  // Show existing vacations for this resource in the selected period
  const { data: existingVacations } = trpc.vacation.list.useQuery(
    {
      resourceId: resourceId || undefined,
      startDate: startDate ? new Date(startDate) : undefined,
      endDate: endDate ? new Date(endDate) : undefined,
    },
    { enabled: !!resourceId && !!startDate && !!endDate, staleTime: 10_000 },
  );

  const utils = trpc.useUtils();

  const createMutation = trpc.vacation.create.useMutation({
    onSuccess: async () => {
      await utils.vacation.list.invalidate();
      onSuccess();
    },
    onError: (err) => setServerError(err.message),
  });

  const isPending = createMutation.isPending;

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setServerError(null);

    if (!resourceId || !startDate || !endDate) {
      setServerError("Please fill in all required fields.");
      return;
    }

    const start = new Date(startDate);
    const end = new Date(endDate);
    if (end < start) {
      setServerError("End date must be on or after start date.");
      return;
    }

    createMutation.mutate({
      resourceId,
      type,
      startDate: start,
      endDate: end,
      note: note || undefined,
      isHalfDay,
      ...(isHalfDay ? { halfDayPart } : {}),
    });
  }

  const inputClass =
    "w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-brand-500 text-sm dark:bg-gray-900 dark:text-gray-100";
  const labelClass = "block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1";
  const resourceList: { id: string; displayName: string; eid: string }[] = resources?.resources ?? [];

  return (
    <div
      className="fixed inset-0 bg-black/50 z-50 flex items-start justify-center overflow-y-auto py-8"
      onClick={(e) => {
        if (e.target === e.currentTarget) onClose();
      }}
    >
      <div
        ref={panelRef}
        className="bg-white dark:bg-gray-800 rounded-xl shadow-2xl w-full max-w-lg mx-4"
        onKeyDown={(e) => { if (e.key === "Escape") onClose(); }}
      >
        {/* Header */}
        <div className="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-700">
          <h2 className="text-lg font-semibold text-gray-900 dark:text-gray-100">Request Vacation</h2>
          <button
            type="button"
            onClick={onClose}
            className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors text-xl leading-none"
            aria-label="Close"
          >
            &times;
          </button>
        </div>

        <form onSubmit={handleSubmit} className="px-6 py-5 space-y-4">
          {/* Resource */}
          {!initialResourceId && (
            <div>
              <label htmlFor="vac-resource" className={labelClass}>
                Resource <span className="text-red-500">*</span><InfoTooltip content="The employee this vacation request is for." />
              </label>
              <select
                id="vac-resource"
                value={resourceId}
                onChange={(e) => setResourceId(e.target.value)}
                className={inputClass}
                required
              >
                <option value="">Select a resource…</option>
                {resourceList.map((r) => (
                  <option key={r.id} value={r.id}>
                    {r.displayName} ({r.eid})
                  </option>
                ))}
              </select>
            </div>
          )}

          {/* Type */}
          <div>
            <label htmlFor="vac-type" className={labelClass}>
              Type <span className="text-red-500">*</span><InfoTooltip content="ANNUAL = paid leave (deducted from entitlement) · SICK = sick leave · PUBLIC_HOLIDAY = national/regional holiday · OTHER = special leave." />
            </label>
            <select
              id="vac-type"
              value={type}
              onChange={(e) => setType(e.target.value as VacationType)}
              className={inputClass}
            >
              {VACATION_TYPES.map((t) => (
                <option key={t} value={t}>
                  {VACATION_TYPE_LABELS[t]}
                </option>
              ))}
            </select>
          </div>

          {/* Dates */}
          <div className="grid grid-cols-2 gap-4">
            <div>
              <label htmlFor="vac-start" className={labelClass}>
                Start Date <span className="text-red-500">*</span><InfoTooltip content="First day of leave (inclusive)." />
              </label>
              <DateInput
                id="vac-start"
                value={startDate}
                onChange={setStartDate}
                className={inputClass}
                required
              />
            </div>
            <div>
              <label htmlFor="vac-end" className={labelClass}>
                End Date <span className="text-red-500">*</span><InfoTooltip content="Last day of leave (inclusive)." />
              </label>
              <DateInput
                id="vac-end"
                value={endDate}
                onChange={setEndDate}
                min={startDate}
                className={inputClass}
                required
              />
            </div>
          </div>

          {/* Half-day toggle */}
          <div className="flex items-center gap-4">
            <label className="flex items-center gap-2 cursor-pointer">
              <input
                type="checkbox"
                checked={isHalfDay}
                onChange={(e) => setIsHalfDay(e.target.checked)}
                className="rounded border-gray-300 dark:border-gray-600 text-brand-600 focus:ring-brand-500"
              />
              <span className="text-sm font-medium text-gray-700 dark:text-gray-300">Half day</span><InfoTooltip content="Request only half a day off (morning or afternoon). Counts as 0.5 days against entitlement." />
            </label>
            {isHalfDay && (
              <div className="flex gap-3">
                <label className="flex items-center gap-1.5 cursor-pointer text-sm text-gray-600 dark:text-gray-400">
                  <input
                    type="radio"
                    value="MORNING"
                    checked={halfDayPart === "MORNING"}
                    onChange={() => setHalfDayPart("MORNING")}
                    className="text-brand-600 focus:ring-brand-500"
                  />
                  Morning
                </label>
                <label className="flex items-center gap-1.5 cursor-pointer text-sm text-gray-600 dark:text-gray-400">
                  <input
                    type="radio"
                    value="AFTERNOON"
                    checked={halfDayPart === "AFTERNOON"}
                    onChange={() => setHalfDayPart("AFTERNOON")}
                    className="text-brand-600 focus:ring-brand-500"
                  />
                  Afternoon
                </label>
              </div>
            )}
          </div>

          {/* Conflict warning */}
          {existingVacations && existingVacations.length > 0 && (
            <div className="rounded-lg bg-amber-50 border border-amber-200 px-4 py-3 text-sm text-amber-700">
              <strong>Existing vacation in this period:</strong>
              <ul className="mt-1 space-y-0.5">
                {existingVacations.map((v) => (
                  <li key={v.id}>
                    {VACATION_TYPE_LABELS[v.type as VacationType]} —{" "}
                    {new Date(v.startDate).toLocaleDateString("en-GB")} to{" "}
                    {new Date(v.endDate).toLocaleDateString("en-GB")} ({v.status})
                  </li>
                ))}
              </ul>
            </div>
          )}

          {/* Team overlap warning */}
          {teamOverlap && teamOverlap.length > 0 && (
            <div className="rounded-lg bg-blue-50 border border-blue-200 px-4 py-3 text-sm text-blue-700">
              <strong>Team members off in this period ({teamOverlap.length}):</strong>
              <ul className="mt-1 space-y-0.5">
                {teamOverlap.map((v) => {
                  const r = v.resource as { displayName: string; eid: string } | null;
                  return (
                    <li key={v.id}>
                      {r?.displayName ?? "—"}{" "}
                      <span className="text-blue-500">({new Date(v.startDate).toLocaleDateString("en-GB")} – {new Date(v.endDate).toLocaleDateString("en-GB")})</span>
                    </li>
                  );
                })}
              </ul>
            </div>
          )}

          {/* Note */}
          <div>
            <label htmlFor="vac-note" className={labelClass}>
              Note (optional)
            </label>
            <textarea
              id="vac-note"
              value={note}
              onChange={(e) => setNote(e.target.value)}
              rows={2}
              maxLength={500}
              className={`${inputClass} resize-none`}
              placeholder="Optional reason or description…"
            />
          </div>

          {/* Server error */}
          {serverError && (
            <div className="rounded-lg bg-red-50 border border-red-200 px-4 py-3 text-sm text-red-700">
              {serverError}
            </div>
          )}

          {/* Footer */}
          <div className="flex items-center justify-end gap-3 pt-2">
            <button
              type="button"
              onClick={onClose}
              disabled={isPending}
              className="px-4 py-2 text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-gray-900 dark:hover:text-gray-100 disabled:opacity-50"
            >
              Cancel
            </button>
            <button
              type="submit"
              disabled={isPending}
              className="px-4 py-2 bg-brand-600 text-white rounded-lg hover:bg-brand-700 text-sm font-medium disabled:opacity-50"
            >
              {isPending ? "Submitting…" : "Submit Request"}
            </button>
          </div>
        </form>
      </div>
    </div>
  );
}
