import { findAllocationEntry, updateAllocationEntry } from "@capakraken/application";
import type { PrismaClient } from "@capakraken/db";
import { TRPCError } from "@trpc/server";
import {
  buildTimelineBatchShiftAuditChanges,
  shiftTimelineAllocationWindow,
  type TimelineBatchShiftMode,
} from "./timeline-allocation-batch-shift-support.js";

export async function applyTimelineBatchAllocationShift(input: {
  db: PrismaClient;
  allocationIds: string[];
  daysDelta: number;
  mode: TimelineBatchShiftMode;
}) {
  if (input.daysDelta === 0) {
    return [];
  }

  const entries = await Promise.all(
    input.allocationIds.map((allocationId) => findAllocationEntry(input.db, allocationId)),
  );
  const resolved = entries.filter(
    (entry): entry is NonNullable<typeof entry> => entry !== null,
  );

  if (resolved.length === 0) {
    throw new TRPCError({ code: "NOT_FOUND", message: "No allocations found" });
  }

  return input.db.$transaction(async (tx) => {
    const updated = [];
    for (const entry of resolved) {
      const existing = entry.entry;
      const shiftedWindow = shiftTimelineAllocationWindow({
        startDate: existing.startDate,
        endDate: existing.endDate,
        daysDelta: input.daysDelta,
        mode: input.mode,
      });

      const result = await updateAllocationEntry(
        tx as unknown as Parameters<typeof updateAllocationEntry>[0],
        {
          id: existing.id,
          demandRequirementUpdate: {
            startDate: shiftedWindow.startDate,
            endDate: shiftedWindow.endDate,
          },
          assignmentUpdate: {
            startDate: shiftedWindow.startDate,
            endDate: shiftedWindow.endDate,
          },
        },
      );
      updated.push(result.allocation);
    }

    await tx.auditLog.create({
      data: {
        entityType: "Allocation",
        entityId: input.allocationIds.join(","),
        action: "UPDATE",
        changes: buildTimelineBatchShiftAuditChanges({
          mode: input.mode,
          daysDelta: input.daysDelta,
          count: resolved.length,
        }),
      },
    });

    return updated;
  });
}
