"use client";

import { clsx } from "clsx";
import { useEffect, useRef, useState } from "react";
import { createPortal } from "react-dom";
import type { AllocationLike, AllocationReadModel, Assignment } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";
import { useInvalidateTimeline } from "~/hooks/useInvalidatePlanningViews.js";
import { useViewportPopover } from "~/hooks/useViewportPopover.js";
import { getPlanningEntryMutationId } from "~/lib/planningEntryIds.js";
import { DateInput } from "~/components/ui/DateInput.js";

interface AllocationPopoverProps {
  allocationId: string;
  projectId: string;
  onClose: () => void;
  onOpenPanel: (projectId: string) => void;
  /** Pixel position relative to the viewport */
  anchorX: number;
  anchorY: number;
}

type AllocationPopoverAssignment = Assignment<AllocationLike>;

export function AllocationPopover({
  allocationId,
  projectId,
  onClose,
  onOpenPanel,
  anchorX,
  anchorY,
}: AllocationPopoverProps) {
  const utils = trpc.useUtils();
  const invalidateTimeline = useInvalidateTimeline();
  const { ref, style } = useViewportPopover({
    anchor: { kind: "point", x: anchorX, y: anchorY },
    width: 300,
    estimatedHeight: 360,
    onClose,
  });

  const { data: allocationView, isLoading } = trpc.allocation.listView.useQuery(
    { projectId },
    { staleTime: 10_000 },
  ) as { data: AllocationReadModel<AllocationLike> | undefined; isLoading: boolean };
  const allocation = allocationView?.assignments.find((entry) => entry.id === allocationId) as AllocationPopoverAssignment | undefined;

  const [hoursPerDay, setHoursPerDay] = useState<number | null>(null);
  const [startDate, setStartDate] = useState<string>("");
  const [endDate, setEndDate] = useState<string>("");
  const [includeSaturday, setIncludeSaturday] = useState(false);
  const [role, setRole] = useState("");

  useEffect(() => {
    if (allocation) {
      setHoursPerDay(allocation.hoursPerDay);
      setStartDate(toDateInput(new Date(allocation.startDate)));
      setEndDate(toDateInput(new Date(allocation.endDate)));
      const meta = allocation.metadata as { includeSaturday?: boolean } | null;
      setIncludeSaturday(meta?.includeSaturday ?? false);
      setRole(allocation.role ?? "");
    }
  }, [allocation]);

  const updateMutation = trpc.timeline.updateAllocationInline.useMutation({
    onSuccess: () => {
      invalidateTimeline();
      void utils.allocation.listView.invalidate();
      onClose();
    },
  });

  function toDateInput(d: Date): string {
    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}`;
  }

  function handleSave() {
    if (!allocation || hoursPerDay === null) return;
    updateMutation.mutate({
      allocationId: getPlanningEntryMutationId(allocation),
      hoursPerDay,
      startDate: startDate ? new Date(startDate) : undefined,
      endDate: endDate ? new Date(endDate) : undefined,
      includeSaturday,
      role: role || undefined,
    });
  }

  if (isLoading || !allocation) {
    const loadingPopover = (
      <div ref={ref} style={style} className="bg-white border border-gray-200 rounded-xl shadow-xl p-4 text-sm text-gray-500">
        Loading...
      </div>
    );
    return typeof document === "undefined" ? loadingPopover : createPortal(loadingPopover, document.body);
  }

  const dailyCostEUR = ((hoursPerDay ?? allocation.hoursPerDay) * (allocation.resource?.lcrCents ?? 0) / 100).toFixed(2);

  const popover = (
    <div
      ref={ref}
      style={style}
      className="bg-white border border-gray-200 rounded-xl shadow-xl overflow-hidden"
    >
      {/* Header */}
      <div className="flex items-center justify-between px-4 py-3 bg-gray-50 border-b border-gray-100">
        <div>
          <span className="text-sm font-semibold text-gray-800">{role}</span>
        </div>
        <button onClick={onClose} className="text-gray-400 hover:text-gray-600 text-lg leading-none">&times;</button>
      </div>

      <div className="p-4 space-y-3">
        {/* Resource */}
        <div className="text-xs text-gray-500">
          Resource: <span className="font-medium text-gray-700">{allocation.resource?.displayName}</span>
          {" "}· <span className="text-gray-400">{allocation.resource?.eid}</span>
        </div>

        {/* Role */}
        <div>
          <label className="block text-xs font-medium text-gray-600 mb-1">Role</label>
          <input
            type="text"
            value={role}
            onChange={(e) => setRole(e.target.value)}
            className="w-full border border-gray-200 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-brand-400"
          />
        </div>

        {/* Hours per day */}
        <div>
          <label className="block text-xs font-medium text-gray-600 mb-1">Hours / day</label>
          <input
            type="number"
            min={0.5}
            max={24}
            step={0.5}
            value={hoursPerDay ?? ""}
            onChange={(e) => setHoursPerDay(parseFloat(e.target.value))}
            className="w-full border border-gray-200 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-brand-400"
          />
        </div>

        {/* Date range */}
        <div className="grid grid-cols-2 gap-2">
          <div>
            <label className="block text-xs font-medium text-gray-600 mb-1">Start</label>
            <DateInput
              value={startDate}
              onChange={setStartDate}
              className="w-full border border-gray-200 rounded-lg px-2 py-1.5 text-xs focus:outline-none focus:ring-2 focus:ring-brand-400"
            />
          </div>
          <div>
            <label className="block text-xs font-medium text-gray-600 mb-1">End</label>
            <DateInput
              value={endDate}
              onChange={setEndDate}
              min={startDate}
              className="w-full border border-gray-200 rounded-lg px-2 py-1.5 text-xs focus:outline-none focus:ring-2 focus:ring-brand-400"
            />
          </div>
        </div>

        {/* Include Saturday */}
        <label className="flex items-center gap-2 cursor-pointer">
          <input
            type="checkbox"
            checked={includeSaturday}
            onChange={(e) => setIncludeSaturday(e.target.checked)}
            className="rounded border-gray-300 text-brand-600 focus:ring-brand-400"
          />
          <span className="text-xs text-gray-700">Include Saturdays</span>
        </label>

        {/* Error */}
        {updateMutation.isError && (
          <p className="text-xs text-red-600">{updateMutation.error.message}</p>
        )}

        {/* Actions */}
        <div className="flex items-center gap-2 pt-1">
          <button
            onClick={handleSave}
            disabled={updateMutation.isPending}
            className={clsx(
              "flex-1 py-1.5 rounded-lg text-sm font-medium transition-colors",
              "bg-brand-600 text-white hover:bg-brand-700 disabled:opacity-50",
            )}
          >
            {updateMutation.isPending ? "Saving…" : "Save"}
          </button>
          <button
            onClick={onClose}
            className="flex-1 py-1.5 rounded-lg text-sm font-medium border border-gray-200 text-gray-600 hover:bg-gray-50"
          >
            Cancel
          </button>
        </div>

        {/* Link to full panel */}
        <button
          onClick={() => { onClose(); onOpenPanel(projectId); }}
          className="w-full text-xs text-brand-600 hover:text-brand-800 text-center pt-1"
        >
          Open Project Panel →
        </button>
      </div>
    </div>
  );

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