import { FillOpenDemandModal } from "~/components/allocations/FillOpenDemandModal.js";
import { AllocationPopover } from "./AllocationPopover.js";
import { BatchAssignPopover } from "./BatchAssignPopover.js";
import { DemandPopover } from "./DemandPopover.js";
import { InlineAllocationEditor } from "./InlineAllocationEditor.js";
import { KeyboardShortcutOverlay } from "./KeyboardShortcutOverlay.js";
import { NewAllocationPopover } from "./NewAllocationPopover.js";
import { ProjectPanel } from "./ProjectPanel.js";
import { ResourceHoverCard } from "./ResourceHoverCard.js";
import type { TimelineDemandEntry, TimelineAssignmentEntry } from "./TimelineContext.js";
import type { OpenDemandAssignment } from "./TimelineProjectPanel.js";
import type { useTimelineDrag } from "~/hooks/useTimelineDrag.js";

interface TimelinePopoversProps {
  isSelfServiceTimeline: boolean;
  hasActivePointerOverlay: boolean;
  popover: {
    allocationId: string;
    projectId: string;
    allocation?: TimelineAssignmentEntry | null;
    x: number;
    y: number;
    contextDate?: Date;
  } | null;
  setPopover: React.Dispatch<React.SetStateAction<TimelinePopoversProps["popover"]>>;
  demandPopover: { demand: TimelineDemandEntry; x: number; y: number } | null;
  setDemandPopover: React.Dispatch<React.SetStateAction<TimelinePopoversProps["demandPopover"]>>;
  newAllocPopover: {
    resourceId: string;
    startDate: Date;
    endDate: Date;
    suggestedProjectId: string | null;
    anchorX: number;
    anchorY: number;
    selectionResourceId: string;
    selectionStart: Date;
    selectionEnd: Date;
  } | null;
  setNewAllocPopover: React.Dispatch<
    React.SetStateAction<TimelinePopoversProps["newAllocPopover"]>
  >;
  enrichedSuggestedProjectId: string | null;
  openPanelProjectId: string | null;
  setOpenPanelProjectId: React.Dispatch<React.SetStateAction<string | null>>;
  openDemandToAssign: OpenDemandAssignment | null;
  setOpenDemandToAssign: React.Dispatch<React.SetStateAction<OpenDemandAssignment | null>>;
  openDemandsByProject: Map<string, TimelineDemandEntry[]>;
  scrollContainerRef: React.RefObject<HTMLDivElement | null>;
  multiSelectState: ReturnType<typeof useTimelineDrag>["multiSelectState"];
  clearMultiSelect: ReturnType<typeof useTimelineDrag>["clearMultiSelect"];
  handleBatchDelete: () => void;
  handleShowBatchAssign: () => void;
  isDeleting: boolean;
  showBatchAssign: boolean;
  setShowBatchAssign: React.Dispatch<React.SetStateAction<boolean>>;
  resourceHover: { resourceId: string; anchorEl: HTMLElement } | null;
  setResourceHover: React.Dispatch<React.SetStateAction<TimelinePopoversProps["resourceHover"]>>;
  inlineEditTarget: {
    allocationId: string;
    startDate: Date;
    endDate: Date;
    hoursPerDay: number;
    barRect: DOMRect;
  } | null;
  setInlineEditTarget: React.Dispatch<
    React.SetStateAction<TimelinePopoversProps["inlineEditTarget"]>
  >;
  showShortcuts: boolean;
  setShowShortcuts: React.Dispatch<React.SetStateAction<boolean>>;
}

function buildDemandAssignment(d: TimelineDemandEntry): OpenDemandAssignment {
  return {
    id: d.id,
    projectId: d.projectId,
    roleId: d.roleId,
    role: d.role,
    headcount: d.requestedHeadcount,
    startDate: new Date(d.startDate),
    endDate: new Date(d.endDate),
    hoursPerDay: d.hoursPerDay,
    ...(d.roleEntity !== undefined ? { roleEntity: d.roleEntity } : {}),
    ...(d.project !== undefined ? { project: d.project } : {}),
  };
}

export function TimelinePopovers({
  isSelfServiceTimeline,
  hasActivePointerOverlay,
  popover,
  setPopover,
  demandPopover,
  setDemandPopover,
  newAllocPopover,
  setNewAllocPopover,
  enrichedSuggestedProjectId,
  openPanelProjectId,
  setOpenPanelProjectId,
  openDemandToAssign,
  setOpenDemandToAssign,
  openDemandsByProject,
  scrollContainerRef,
  multiSelectState,
  clearMultiSelect,
  handleBatchDelete,
  handleShowBatchAssign,
  isDeleting,
  showBatchAssign,
  setShowBatchAssign,
  resourceHover,
  setResourceHover,
  inlineEditTarget,
  setInlineEditTarget,
  showShortcuts,
  setShowShortcuts,
}: TimelinePopoversProps) {
  return (
    <>
      {/* Allocation / Demand popover (click path) */}
      {!isSelfServiceTimeline &&
        !hasActivePointerOverlay &&
        popover &&
        (() => {
          const clickedDemand = openDemandsByProject
            .get(popover.projectId)
            ?.find((d) => d.id === popover.allocationId);
          if (clickedDemand) {
            return (
              <DemandPopover
                demand={clickedDemand}
                onClose={() => setPopover(null)}
                onOpenPanel={(pid) => {
                  setPopover(null);
                  setOpenPanelProjectId(pid);
                }}
                onFillDemand={(d) => {
                  setPopover(null);
                  setOpenDemandToAssign(buildDemandAssignment(d));
                }}
                anchorX={popover.x}
                anchorY={popover.y}
                ignoreScrollContainers={[scrollContainerRef]}
              />
            );
          }
          return (
            <AllocationPopover
              allocationId={popover.allocationId}
              projectId={popover.projectId}
              initialAllocation={popover.allocation ?? null}
              onClose={() => setPopover(null)}
              onOpenPanel={(pid) => {
                setPopover(null);
                setOpenPanelProjectId(pid);
              }}
              anchorX={popover.x}
              anchorY={popover.y}
              ignoreScrollContainers={[scrollContainerRef]}
              {...(popover.contextDate ? { contextDate: popover.contextDate } : {})}
            />
          );
        })()}

      {/* Demand popover (context menu path) */}
      {!isSelfServiceTimeline && !hasActivePointerOverlay && demandPopover && (
        <DemandPopover
          demand={demandPopover.demand}
          onClose={() => setDemandPopover(null)}
          onOpenPanel={(pid) => {
            setDemandPopover(null);
            setOpenPanelProjectId(pid);
          }}
          onFillDemand={(d) => {
            setDemandPopover(null);
            setOpenDemandToAssign(buildDemandAssignment(d));
          }}
          anchorX={demandPopover.x}
          anchorY={demandPopover.y}
          ignoreScrollContainers={[scrollContainerRef]}
        />
      )}

      {/* New allocation popover */}
      {!isSelfServiceTimeline && newAllocPopover && (
        <NewAllocationPopover
          resourceId={newAllocPopover.resourceId}
          startDate={newAllocPopover.startDate}
          endDate={newAllocPopover.endDate}
          suggestedProjectId={enrichedSuggestedProjectId}
          anchorX={newAllocPopover.anchorX}
          anchorY={newAllocPopover.anchorY}
          onClose={() => setNewAllocPopover(null)}
          onCreated={() => setNewAllocPopover(null)}
          ignoreScrollContainers={[scrollContainerRef]}
        />
      )}

      {/* Project side panel */}
      {!isSelfServiceTimeline && openPanelProjectId && (
        <ProjectPanel projectId={openPanelProjectId} onClose={() => setOpenPanelProjectId(null)} />
      )}

      {/* Open-demand assignment modal */}
      {!isSelfServiceTimeline && openDemandToAssign && (
        <FillOpenDemandModal
          allocation={openDemandToAssign}
          onClose={() => setOpenDemandToAssign(null)}
          onSuccess={() => setOpenDemandToAssign(null)}
        />
      )}

      {/* Multi-select floating action bar + batch assign */}
      {showBatchAssign && multiSelectState.dateRange && (
        <BatchAssignPopover
          resourceIds={multiSelectState.selectedResourceIds}
          startDate={multiSelectState.dateRange.start}
          endDate={multiSelectState.dateRange.end}
          onClose={() => setShowBatchAssign(false)}
          onCreated={() => {
            setShowBatchAssign(false);
            clearMultiSelect();
          }}
        />
      )}

      {/* Resource hover card */}
      {!hasActivePointerOverlay && resourceHover && (
        <ResourceHoverCard
          resourceId={resourceHover.resourceId}
          anchorEl={resourceHover.anchorEl}
          onClose={() => setResourceHover(null)}
        />
      )}

      {/* Inline allocation editor */}
      {inlineEditTarget && (
        <InlineAllocationEditor
          allocationId={inlineEditTarget.allocationId}
          initialStartDate={inlineEditTarget.startDate}
          initialEndDate={inlineEditTarget.endDate}
          initialHoursPerDay={inlineEditTarget.hoursPerDay}
          barRect={inlineEditTarget.barRect}
          onClose={() => setInlineEditTarget(null)}
          onSaved={() => setInlineEditTarget(null)}
        />
      )}

      {/* Keyboard shortcut overlay */}
      {showShortcuts && <KeyboardShortcutOverlay onClose={() => setShowShortcuts(false)} />}

      {/* Keyboard shortcut hint button */}
      <button
        type="button"
        onClick={() => setShowShortcuts((prev) => !prev)}
        title="Keyboard shortcuts (?)"
        className="fixed bottom-6 right-6 z-40 rounded-full w-8 h-8 flex items-center justify-center bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 shadow text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 text-sm font-medium"
      >
        ?
      </button>
    </>
  );
}
