import {
  calculateSAH,
  getMonthRange,
  DEFAULT_CALCULATION_RULES,
} from "@capakraken/engine";
import type { CalculationRule, SpainScheduleRule, WeekdayAvailability } from "@capakraken/shared";
import type { TRPCContext } from "../trpc.js";
import { loadResourceGraphAvailability } from "./computation-graph-resource-availability.js";

export type ResourceGraphInput = {
  resourceId: string;
  month: string;
};

export async function loadResourceGraphSnapshot(
  ctx: { db: TRPCContext["db"] },
  input: ResourceGraphInput,
) {
  const [year, month] = input.month.split("-").map(Number) as [number, number];
  const { start: monthStart, end: monthEnd } = getMonthRange(year, month);

  const resource = await ctx.db.resource.findUniqueOrThrow({
    where: { id: input.resourceId },
    select: {
      id: true,
      displayName: true,
      eid: true,
      fte: true,
      lcrCents: true,
      chargeabilityTarget: true,
      countryId: true,
      federalState: true,
      metroCityId: true,
      availability: true,
      country: { select: { id: true, code: true, name: true, dailyWorkingHours: true, scheduleRules: true } },
      metroCity: { select: { id: true, name: true } },
      managementLevelGroup: { select: { id: true, name: true, targetPercentage: true } },
    },
  });

  const dailyHours = resource.country?.dailyWorkingHours ?? 8;
  const scheduleRules = resource.country?.scheduleRules as SpainScheduleRule | null;
  const targetPct = resource.managementLevelGroup?.targetPercentage ?? (resource.chargeabilityTarget / 100);

  const availability = resource.availability as WeekdayAvailability | null;
  const weeklyAvailability: WeekdayAvailability = availability ?? {
    monday: dailyHours,
    tuesday: dailyHours,
    wednesday: dailyHours,
    thursday: dailyHours,
    friday: dailyHours,
    saturday: 0,
    sunday: 0,
  };

  const assignments = await ctx.db.assignment.findMany({
    where: {
      resourceId: input.resourceId,
      startDate: { lte: monthEnd },
      endDate: { gte: monthStart },
      status: { in: ["CONFIRMED", "ACTIVE", "PROPOSED"] },
    },
    select: {
      id: true,
      hoursPerDay: true,
      startDate: true,
      endDate: true,
      dailyCostCents: true,
      status: true,
      project: {
        select: {
          id: true,
          name: true,
          shortCode: true,
          budgetCents: true,
          winProbability: true,
          utilizationCategory: { select: { code: true } },
        },
      },
    },
  });

  const availabilitySummary = await loadResourceGraphAvailability({
    db: ctx.db,
    resource,
    weeklyAvailability,
    monthStart,
    monthEnd,
  });

  let calcRules: CalculationRule[] = DEFAULT_CALCULATION_RULES;
  try {
    const dbRules = await ctx.db.calculationRule.findMany({
      where: { isActive: true },
      orderBy: [{ priority: "desc" }],
    });
    if (dbRules.length > 0) {
      calcRules = dbRules as unknown as CalculationRule[];
    }
  } catch {
    // table may not exist yet
  }

  const sahResult = calculateSAH({
    dailyWorkingHours: dailyHours,
    scheduleRules,
    fte: resource.fte,
    periodStart: monthStart,
    periodEnd: monthEnd,
    publicHolidays: availabilitySummary.publicHolidayStrings,
    absenceDays: availabilitySummary.absenceDateStrings,
  });

  return {
    assignments,
    calcRules,
    dailyHours,
    monthEnd,
    monthStart,
    resource,
    sahResult,
    scheduleRules,
    targetPct,
    weeklyAvailability,
    ...availabilitySummary,
  };
}
