import type { PrismaClient, Prisma } from "@capakraken/db";
import { type UpdateAssignmentInput } from "@capakraken/shared";
import { TRPCError } from "@trpc/server";
import {
  ASSIGNMENT_RELATIONS_INCLUDE,
  type AssignmentWithRelations,
} from "./create-assignment.js";

type DbClient = PrismaClient | Prisma.TransactionClient;

export async function updateAssignment(
  db: DbClient,
  id: string,
  input: UpdateAssignmentInput,
): Promise<AssignmentWithRelations> {
  const existing = await db.assignment.findUnique({
    where: { id },
    include: ASSIGNMENT_RELATIONS_INCLUDE,
  });

  if (!existing) {
    throw new TRPCError({ code: "NOT_FOUND", message: "Assignment not found" });
  }

  const updatedAssignment = await db.assignment.update({
    where: { id },
    data: {
      ...(input.resourceId !== undefined ? { resourceId: input.resourceId } : {}),
      ...(input.projectId !== undefined ? { projectId: input.projectId } : {}),
      ...(input.demandRequirementId !== undefined
        ? { demandRequirementId: input.demandRequirementId }
        : {}),
      ...(input.startDate !== undefined ? { startDate: input.startDate } : {}),
      ...(input.endDate !== undefined ? { endDate: input.endDate } : {}),
      ...(input.hoursPerDay !== undefined ? { hoursPerDay: input.hoursPerDay } : {}),
      ...(input.percentage !== undefined ? { percentage: input.percentage } : {}),
      ...(input.role !== undefined ? { role: input.role } : {}),
      ...(input.roleId !== undefined ? { roleId: input.roleId } : {}),
      ...(input.dailyCostCents !== undefined ? { dailyCostCents: input.dailyCostCents } : {}),
      ...(input.status !== undefined ? { status: input.status } : {}),
      ...(input.metadata !== undefined
        ? { metadata: input.metadata as unknown as Prisma.InputJsonValue }
        : {}),
    },
    include: ASSIGNMENT_RELATIONS_INCLUDE,
  });

  await db.auditLog.create({
    data: {
      entityType: "Assignment",
      entityId: id,
      action: "UPDATE",
      changes: {
        before: {
          resourceId: existing.resourceId,
          projectId: existing.projectId,
          demandRequirementId: existing.demandRequirementId,
          startDate: existing.startDate,
          endDate: existing.endDate,
          hoursPerDay: existing.hoursPerDay,
          percentage: existing.percentage,
          role: existing.role,
          roleId: existing.roleId,
          dailyCostCents: existing.dailyCostCents,
          status: existing.status,
        },
        after: {
          resourceId: updatedAssignment.resourceId,
          projectId: updatedAssignment.projectId,
          demandRequirementId: updatedAssignment.demandRequirementId,
          startDate: updatedAssignment.startDate,
          endDate: updatedAssignment.endDate,
          hoursPerDay: updatedAssignment.hoursPerDay,
          percentage: updatedAssignment.percentage,
          role: updatedAssignment.role,
          roleId: updatedAssignment.roleId,
          dailyCostCents: updatedAssignment.dailyCostCents,
          status: updatedAssignment.status,
        },
      } as unknown as Prisma.InputJsonValue,
    },
  });

  return updatedAssignment;
}
