import {
  fmtDate,
} from "./timeline-read-shared.js";
import {
  anonymizeResourceOnEntry,
  summarizeTimelineEntries,
} from "./timeline-entry-response-support.js";
import {
  summarizeHolidayOverlays,
} from "./timeline-holiday-read.js";

type TimelineAnonymizationDirectory = Parameters<typeof anonymizeResourceOnEntry>[1];

export function buildTimelineProjectContextSummary(input: {
  allocations: Array<{ projectId: string | null; resourceId: string | null }>;
  demands: Array<{ projectId: string | null }>;
  assignments: Array<{ projectId: string | null; resourceId: string | null }>;
  resourceIds: string[];
  allResourceAllocations: unknown[];
  assignmentConflicts: Array<{ crossProjectOverlapCount: number }>;
  holidayOverlays: Parameters<typeof summarizeHolidayOverlays>[0];
}) {
  return {
    ...summarizeTimelineEntries({
      allocations: input.allocations,
      demands: input.demands,
      assignments: input.assignments,
    }),
    resourceIds: input.resourceIds.length,
    allResourceAllocationCount: input.allResourceAllocations.length,
    conflictedAssignmentCount: input.assignmentConflicts.filter(
      (item) => item.crossProjectOverlapCount > 0,
    ).length,
    ...summarizeHolidayOverlays(input.holidayOverlays),
  };
}

export function buildTimelineProjectContextResponse<
  TProject,
  TAllocation extends { resource?: { id: string } | null },
  TDemand,
  TAssignment extends { resource?: { id: string } | null },
  TBooking extends { resource?: { id: string } | null },
>(input: {
  project: TProject;
  allocations: TAllocation[];
  demands: TDemand[];
  assignments: TAssignment[];
  allResourceAllocations: TBooking[];
  resourceIds: string[];
  directory: TimelineAnonymizationDirectory;
}) {
  return {
    project: input.project,
    allocations: input.allocations.map((allocation) =>
      anonymizeResourceOnEntry(allocation, input.directory),
    ),
    demands: input.demands,
    assignments: input.assignments.map((assignment) =>
      anonymizeResourceOnEntry(assignment, input.directory),
    ),
    allResourceAllocations: input.allResourceAllocations.map((allocation) =>
      anonymizeResourceOnEntry(allocation, input.directory),
    ),
    resourceIds: input.resourceIds,
  };
}

export function buildTimelineProjectContextDetailResponse<
  TProject,
  TAllocation extends {
    projectId: string | null;
    resourceId: string | null;
    resource?: { id: string } | null;
  },
  TDemand extends { projectId: string | null },
  TAssignment extends {
    projectId: string | null;
    resourceId: string | null;
    resource?: { id: string } | null;
  },
  TBooking extends { resource?: { id: string } | null },
  TConflict extends { crossProjectOverlapCount: number },
>(input: {
  project: TProject;
  period: { startDate: Date; endDate: Date };
  allocations: TAllocation[];
  demands: TDemand[];
  assignments: TAssignment[];
  allResourceAllocations: TBooking[];
  resourceIds: string[];
  assignmentConflicts: TConflict[];
  holidayOverlays: Parameters<typeof summarizeHolidayOverlays>[0];
  directory: TimelineAnonymizationDirectory;
}) {
  const base = buildTimelineProjectContextResponse({
    project: input.project,
    allocations: input.allocations,
    demands: input.demands,
    assignments: input.assignments,
    allResourceAllocations: input.allResourceAllocations,
    resourceIds: input.resourceIds,
    directory: input.directory,
  });

  return {
    ...base,
    period: {
      startDate: fmtDate(input.period.startDate),
      endDate: fmtDate(input.period.endDate),
    },
    summary: buildTimelineProjectContextSummary({
      allocations: input.allocations,
      demands: input.demands,
      assignments: input.assignments,
      resourceIds: input.resourceIds,
      allResourceAllocations: input.allResourceAllocations,
      assignmentConflicts: input.assignmentConflicts,
      holidayOverlays: input.holidayOverlays,
    }),
    assignmentConflicts: input.assignmentConflicts,
    holidayOverlays: input.holidayOverlays,
  };
}
