import type { AllocationWithDetails, ColumnDef } from "@nexus/shared";
import type { CollapsedAllocationGroups } from "./allocationGroupState.js";
import { formatDate } from "~/lib/format.js";
import { AllocationRow } from "./AllocationRow.js";

type ProjectSubGroup = {
  projectId: string;
  projectName: string;
  projectCode: string;
  allocations: AllocationWithDetails[];
  typicalHoursPerDay: number;
  earliestStart: Date;
  latestEnd: Date;
};

export type AllocGroup = {
  resourceId: string;
  resourceName: string;
  eid: string;
  chapter: string | null;
  allocations: AllocationWithDetails[];
  projectSubGroups: ProjectSubGroup[];
};

/** Fragment wrapper for grouped rows — avoids unnecessary DOM nodes */
function GroupRows({ children }: { children: React.ReactNode }) {
  return <>{children}</>;
}

type AllocationGroupedBodyProps = {
  groups: AllocGroup[];
  collapsedGroups: CollapsedAllocationGroups;
  expandedSubGroups: Set<string>;
  visibleColumns: ColumnDef[];
  selectedIds: Set<string>;
  isAllSelected: (ids: string[]) => boolean;
  isIndeterminate?: (ids: string[]) => boolean;
  onToggleSelection: (id: string) => void;
  onToggleAllSelection: (ids: string[]) => void;
  onToggleGroup: (resourceId: string) => void;
  onToggleSubGroup: (resourceId: string, projectId: string) => void;
  onEdit: (alloc: AllocationWithDetails) => void;
  onRequestDelete: (alloc: AllocationWithDetails) => void;
  deleteDisabled: boolean;
  formatPeriod: (alloc: AllocationWithDetails) => string;
};

export function AllocationGroupedBody({
  groups,
  collapsedGroups,
  expandedSubGroups,
  visibleColumns,
  selectedIds,
  isAllSelected,
  onToggleSelection,
  onToggleAllSelection,
  onToggleGroup,
  onToggleSubGroup,
  onEdit,
  onRequestDelete,
  deleteDisabled,
  formatPeriod,
}: AllocationGroupedBodyProps) {
  return (
    <>
      {groups.map((group) => {
        const isCollapsed = collapsedGroups === "all" || collapsedGroups.has(group.resourceId);
        const groupAllocIds = group.allocations.map((a) => a.id);
        const allGroupSelected = isAllSelected(groupAllocIds);
        const groupIndeterminate =
          !allGroupSelected && groupAllocIds.some((id) => selectedIds.has(id));
        return (
          <GroupRows key={group.resourceId}>
            {/* Group header */}
            <tr
              data-testid="allocation-group-header"
              className="bg-gray-50 dark:bg-gray-800/50 cursor-pointer select-none hover:bg-gray-100 dark:hover:bg-gray-800/80 transition-colors"
              onClick={() => onToggleGroup(group.resourceId)}
              onKeyDown={(e) => {
                if (e.key === "Enter" || e.key === " ") {
                  e.preventDefault();
                  onToggleGroup(group.resourceId);
                }
              }}
              tabIndex={0}
              role="button"
              aria-expanded={!isCollapsed}
            >
              <td className="px-4 py-2.5" onClick={(e) => e.stopPropagation()}>
                <input
                  type="checkbox"
                  checked={allGroupSelected}
                  ref={(el) => {
                    if (el) el.indeterminate = groupIndeterminate;
                  }}
                  onChange={() => onToggleAllSelection(groupAllocIds)}
                  className="rounded border-gray-300 dark:border-gray-600"
                />
              </td>
              <td colSpan={visibleColumns.length + 1} className="px-4 py-2.5">
                <div className="flex items-center gap-2">
                  <span className="text-gray-400 dark:text-gray-500 text-xs">
                    {isCollapsed ? "▸" : "▾"}
                  </span>
                  <span className="text-sm font-semibold text-gray-900 dark:text-gray-100">
                    {group.resourceName}
                  </span>
                  {group.eid && (
                    <span className="text-xs font-mono text-gray-400 dark:text-gray-500">
                      {group.eid}
                    </span>
                  )}
                  {group.chapter && (
                    <span className="text-xs text-gray-400 dark:text-gray-500">
                      · {group.chapter}
                    </span>
                  )}
                  <span className="inline-flex items-center rounded-full bg-gray-200 px-2 py-0.5 text-xs font-medium text-gray-600 dark:bg-gray-700 dark:text-gray-300">
                    {group.allocations.length}
                  </span>
                </div>
              </td>
            </tr>
            {/* Project sub-groups within person */}
            {!isCollapsed &&
              group.projectSubGroups.map((subGroup) => {
                const subKey = `${group.resourceId}::${subGroup.projectId}`;
                const isSubExpanded = expandedSubGroups.has(subKey);

                // Single allocation for this project — render directly, no sub-group header
                if (subGroup.allocations.length === 1) {
                  const alloc = subGroup.allocations[0]!;
                  return (
                    <GroupRows key={subKey}>
                      <AllocationRow
                        alloc={alloc}
                        visibleColumns={visibleColumns}
                        isGrouped
                        rowIndex={0}
                        isSelected={selectedIds.has(alloc.id)}
                        onToggleSelection={() => onToggleSelection(alloc.id)}
                        onEdit={() => onEdit(alloc)}
                        onRequestDelete={() => onRequestDelete(alloc)}
                        deleteDisabled={deleteDisabled}
                        formatPeriod={formatPeriod}
                      />
                    </GroupRows>
                  );
                }

                // Multiple allocations — show collapsible project sub-group
                const subAllocIds = subGroup.allocations.map((a) => a.id);
                const allSubSelected = isAllSelected(subAllocIds);
                const subIndeterminate =
                  !allSubSelected && subAllocIds.some((id) => selectedIds.has(id));
                return (
                  <GroupRows key={subKey}>
                    <tr
                      data-testid="allocation-subgroup-header"
                      className="bg-gray-25 dark:bg-gray-850/30 cursor-pointer select-none hover:bg-gray-100/60 dark:hover:bg-gray-800/40 transition-colors"
                      onClick={() => onToggleSubGroup(group.resourceId, subGroup.projectId)}
                      tabIndex={0}
                      role="button"
                      aria-expanded={isSubExpanded}
                      onKeyDown={(e) => {
                        if (e.key === "Enter" || e.key === " ") {
                          e.preventDefault();
                          onToggleSubGroup(group.resourceId, subGroup.projectId);
                        }
                      }}
                    >
                      <td className="px-4 py-2" onClick={(e) => e.stopPropagation()}>
                        <input
                          type="checkbox"
                          checked={allSubSelected}
                          ref={(el) => {
                            if (el) el.indeterminate = subIndeterminate;
                          }}
                          onChange={() => onToggleAllSelection(subAllocIds)}
                          className="rounded border-gray-300 dark:border-gray-600"
                        />
                      </td>
                      <td colSpan={visibleColumns.length + 1} className="px-4 py-2">
                        <div className="flex items-center gap-2 pl-4">
                          <span className="text-gray-400 dark:text-gray-500 text-xs">
                            {isSubExpanded ? "▾" : "▸"}
                          </span>
                          <span className="font-mono text-xs text-gray-400 dark:text-gray-500">
                            {subGroup.projectCode}
                          </span>
                          <span className="text-sm text-gray-700 dark:text-gray-300">
                            {subGroup.projectName}
                          </span>
                          <span className="text-xs text-gray-400 dark:text-gray-500">
                            {formatDate(subGroup.earliestStart)} → {formatDate(subGroup.latestEnd)}
                          </span>
                          <span className="text-xs text-gray-500 dark:text-gray-400">
                            {subGroup.typicalHoursPerDay}h/day
                          </span>
                          <span className="inline-flex items-center rounded-full bg-gray-200 px-1.5 py-0.5 text-[10px] font-medium text-gray-500 dark:bg-gray-700 dark:text-gray-400">
                            {subGroup.allocations.length}
                          </span>
                        </div>
                      </td>
                    </tr>
                    {isSubExpanded &&
                      subGroup.allocations.map((alloc, idx) => (
                        <AllocationRow
                          key={alloc.id}
                          alloc={alloc}
                          visibleColumns={visibleColumns}
                          isGrouped
                          rowIndex={idx}
                          isSelected={selectedIds.has(alloc.id)}
                          onToggleSelection={() => onToggleSelection(alloc.id)}
                          onEdit={() => onEdit(alloc)}
                          onRequestDelete={() => onRequestDelete(alloc)}
                          deleteDisabled={deleteDisabled}
                          formatPeriod={formatPeriod}
                        />
                      ))}
                  </GroupRows>
                );
              })}
          </GroupRows>
        );
      })}
    </>
  );
}
