import { buildResourceAllocationSummary } from "./computation-graph-resource-allocation.js";
import { readResourceBudgetGraph } from "./computation-graph-resource-budget.js";
import { buildResourceGraphSnapshot } from "./computation-graph-resource-graph.js";
import {
  loadResourceGraphSnapshot,
  type ResourceGraphInput,
} from "./computation-graph-resource-snapshot.js";

export async function readResourceGraphSnapshot(
  ctx: Parameters<typeof loadResourceGraphSnapshot>[0],
  input: ResourceGraphInput,
) {
  const {
    absenceDateStrings,
    absenceDayEquivalent,
    absenceDays,
    absenceHoursDeduction,
    assignments,
    baseAvailableHours,
    baseWorkingDays,
    calcRules,
    dailyHours,
    effectiveAvailableHours,
    effectiveHoursPerWorkingDay,
    effectiveWorkingDays,
    halfDayCount,
    holidayExamples,
    holidayScopeBreakdown,
    holidayScopeSummary,
    monthEnd,
    monthStart,
    publicHolidayCount,
    publicHolidayHoursDeduction,
    publicHolidayWorkdayCount,
    resolvedHolidays,
    resource,
    sahResult,
    scheduleRules,
    sickDayCount,
    targetPct,
    vacationDayCount,
    weeklyAvailability,
  } = await loadResourceGraphSnapshot(ctx, input);

  const allocationSummary = buildResourceAllocationSummary({
    assignments,
    absenceDays,
    calcRules,
    effectiveAvailableHours,
    monthEnd,
    monthStart,
    resourceFte: resource.fte,
    resourceLcrCents: resource.lcrCents,
    targetPct,
    weeklyAvailability,
  });
  const { nodes: budgetNodes, links: budgetLinks } = await readResourceBudgetGraph(
    ctx.db,
    assignments,
    monthStart,
    monthEnd,
  );

  return buildResourceGraphSnapshot({
    month: input.month,
    resource,
    dailyHours,
    scheduleRules,
    targetPct,
    weeklyAvailability,
    holidayScopeSummary,
    holidayExamples,
    holidayScopeBreakdown,
    calcRulesCount: calcRules.length,
    assignmentCount: assignments.length,
    absenceCount: absenceDateStrings.length,
    vacationDayCount,
    sickDayCount,
    halfDayCount,
    publicHolidayCount,
    publicHolidayWorkdayCount,
    publicHolidayHoursDeduction,
    absenceHoursDeduction,
    sahCalendarDays: sahResult.calendarDays,
    sahWeekendDays: sahResult.weekendDays,
    baseWorkingDays,
    effectiveWorkingDays,
    baseAvailableHours,
    effectiveAvailableHours,
    effectiveHoursPerWorkingDay,
    totalWorkingDaysInMonth: allocationSummary.totalWorkingDaysInMonth,
    totalAllocHours: allocationSummary.totalAllocHours,
    totalAllocCostCents: allocationSummary.totalAllocCostCents,
    totalChargeableHours: allocationSummary.totalChargeableHours,
    totalProjectCostCents: allocationSummary.totalProjectCostCents,
    hasRulesEffect: allocationSummary.hasRulesEffect,
    dailyCostCents: allocationSummary.dailyCostCents,
    avgHoursPerDay: allocationSummary.avgHoursPerDay,
    utilizationPct: allocationSummary.utilizationPct,
    forecast: allocationSummary.forecast,
    chargeableHours: allocationSummary.chargeableHours,
    budgetNodes,
    budgetLinks,
    resolvedHolidays: resolvedHolidays.map((holiday) => ({
      date: holiday.date,
      name: holiday.name,
      scope: holiday.scope,
      calendarName: holiday.calendarName,
      sourceType: holiday.sourceType ?? null,
    })),
    assignmentBreakdown: allocationSummary.assignmentBreakdown,
    absenceDayEquivalent,
  });
}
