import type { TimelineAssignmentEntry } from "./TimelineContext.js";
import type { ResourceCapacitySeries } from "./timelineCapacity.js";

export type ProjectDayMetric = {
  projH: number;
  totalH: number;
  capacityH: number;
};

type ProjectMetricRow = {
  resource: { id: string };
  allocs: TimelineAssignmentEntry[];
};

type ProjectMetricGroup = {
  id: string;
  resourceRows: ProjectMetricRow[];
};

export function getProjectRowMetricsKey(projectId: string, resourceId: string): string {
  return `${projectId}:${resourceId}`;
}

export function buildProjectRowMetrics(
  dates: Date[],
  projectGroups: ProjectMetricGroup[],
  resourceTotalHoursById: Map<string, number[]>,
  resourceCapacityById: Map<string, ResourceCapacitySeries>,
): Map<string, ProjectDayMetric[]> {
  const dateIndexByTime = new Map<number, number>();
  dates.forEach((date, index) => {
    const normalized = new Date(date);
    normalized.setHours(0, 0, 0, 0);
    dateIndexByTime.set(normalized.getTime(), index);
  });

  const nextMetrics = new Map<string, ProjectDayMetric[]>();

  for (const project of projectGroups) {
    for (const { resource, allocs } of project.resourceRows) {
      const projectHours = new Array<number>(dates.length).fill(0);
      const capacity = resourceCapacityById.get(resource.id);

      for (const alloc of allocs) {
        const current = new Date(alloc.startDate);
        current.setHours(0, 0, 0, 0);
        const end = new Date(alloc.endDate);
        end.setHours(0, 0, 0, 0);

        while (current.getTime() <= end.getTime()) {
          const dayIndex = dateIndexByTime.get(current.getTime());
          if (dayIndex !== undefined) {
            projectHours[dayIndex] =
              (projectHours[dayIndex] ?? 0) +
              alloc.hoursPerDay * (capacity?.bookingFactorsByDay[dayIndex] ?? 1);
          }
          current.setDate(current.getDate() + 1);
        }
      }

      const totalHours = resourceTotalHoursById.get(resource.id);
      nextMetrics.set(
        getProjectRowMetricsKey(project.id, resource.id),
        projectHours.map((projH, dayIndex) => ({
          projH,
          totalH: totalHours?.[dayIndex] ?? 0,
          capacityH: capacity?.capacityHoursByDay[dayIndex] ?? 8,
        })),
      );
    }
  }

  return nextMetrics;
}
