"use client";

import { useState, useEffect, useRef } from "react";
import { createPortal } from "react-dom";
import { trpc } from "~/lib/trpc/client.js";
import { useInvalidatePlanningViews } from "~/hooks/useInvalidatePlanningViews.js";

interface InlineAllocationEditorProps {
  allocationId: string;
  initialStartDate: Date;
  initialEndDate: Date;
  initialHoursPerDay: number;
  /** Bounding rect of the allocation bar (used for positioning) */
  barRect: DOMRect;
  onClose: () => void;
  onSaved: () => void;
}

function toIso(d: Date): string {
  return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
}

export function InlineAllocationEditor({
  allocationId,
  initialStartDate,
  initialEndDate,
  initialHoursPerDay,
  barRect,
  onClose,
  onSaved,
}: InlineAllocationEditorProps) {
  const [startDate, setStartDate] = useState(toIso(initialStartDate));
  const [endDate, setEndDate] = useState(toIso(initialEndDate));
  const [hoursPerDay, setHoursPerDay] = useState(initialHoursPerDay);
  const [error, setError] = useState<string | null>(null);
  const panelRef = useRef<HTMLDivElement>(null);
  const invalidatePlanningViews = useInvalidatePlanningViews();

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const updateMutation = (trpc.allocation.update.useMutation as any)({
    onSuccess: () => {
      void invalidatePlanningViews();
      onSaved();
    },
    onError: (err: { message: string }) => {
      setError(err.message || "Save failed");
    },
  }) as { mutate: (input: unknown) => void; isPending: boolean };

  // Position: below the bar, clamped to viewport
  const top = Math.min(barRect.bottom + 6, window.innerHeight - 220);
  const left = Math.min(Math.max(8, barRect.left), window.innerWidth - 248);

  // Close on click outside
  useEffect(() => {
    const handler = (e: MouseEvent) => {
      if (panelRef.current && !panelRef.current.contains(e.target as Node)) {
        onClose();
      }
    };
    document.addEventListener("mousedown", handler);
    return () => document.removeEventListener("mousedown", handler);
  }, [onClose]);

  // Close on Escape
  useEffect(() => {
    const handler = (e: KeyboardEvent) => {
      if (e.key === "Escape") onClose();
    };
    window.addEventListener("keydown", handler);
    return () => window.removeEventListener("keydown", handler);
  }, [onClose]);

  function handleSave(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    const s = new Date(startDate);
    const en = new Date(endDate);
    if (en < s) {
      setError("End date must be after start date");
      return;
    }
    updateMutation.mutate({
      id: allocationId,
      data: { startDate: s, endDate: en, hoursPerDay },
    });
  }

  const panel = (
    <div
      ref={panelRef}
      style={{ position: "fixed", top, left, zIndex: 60, width: 240 }}
      className="bg-white dark:bg-gray-800 rounded-xl shadow-xl border border-gray-200 dark:border-gray-700 p-3 space-y-2.5"
    >
      <div className="text-xs font-semibold text-gray-700 dark:text-gray-200">Edit Allocation</div>
      <form onSubmit={handleSave} className="space-y-2">
        <div>
          <label className="block text-[11px] text-gray-500 dark:text-gray-400 mb-0.5">
            Start date
          </label>
          <input
            type="date"
            value={startDate}
            onChange={(e) => setStartDate(e.target.value)}
            className="w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 px-2 py-1 text-xs text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-1 focus:ring-brand-500"
            autoFocus
          />
        </div>
        <div>
          <label className="block text-[11px] text-gray-500 dark:text-gray-400 mb-0.5">
            End date
          </label>
          <input
            type="date"
            value={endDate}
            min={startDate}
            onChange={(e) => setEndDate(e.target.value)}
            className="w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 px-2 py-1 text-xs text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-1 focus:ring-brand-500"
          />
        </div>
        <div>
          <label className="block text-[11px] text-gray-500 dark:text-gray-400 mb-0.5">
            Hours / day
          </label>
          <input
            type="number"
            value={hoursPerDay}
            min={0.5}
            max={24}
            step={0.5}
            onChange={(e) => setHoursPerDay(Number(e.target.value))}
            className="w-full rounded-md border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-900 px-2 py-1 text-xs text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-1 focus:ring-brand-500"
          />
        </div>
        {error && <p className="text-[11px] text-red-600 dark:text-red-400">{error}</p>}
        <div className="flex items-center gap-2 pt-0.5">
          <button
            type="submit"
            disabled={updateMutation.isPending}
            className="flex-1 rounded-md bg-brand-600 px-2 py-1.5 text-xs font-semibold text-white hover:bg-brand-700 disabled:opacity-50 transition-colors"
          >
            {updateMutation.isPending ? "Saving…" : "Save"}
          </button>
          <button
            type="button"
            onClick={onClose}
            className="rounded-md border border-gray-300 dark:border-gray-600 px-2 py-1.5 text-xs font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-800 transition-colors"
          >
            Cancel
          </button>
        </div>
      </form>
    </div>
  );

  return typeof document === "undefined" ? panel : createPortal(panel, document.body);
}
