import type { PrismaClient } from "@capakraken/db";
import type { FillOpenDemandByAllocationInput } from "@capakraken/shared";
import { TRPCError } from "@trpc/server";
import { fillDemandRequirement } from "./fill-demand-requirement.js";
import { loadAllocationEntry } from "./load-allocation-entry.js";

export interface FillOpenDemandResult {
  strategy: "demand_requirement" | "placeholder";
  createdAllocation: {
    id: string;
    projectId: string;
    resourceId: string | null;
  };
  updatedAllocation: {
    id: string;
    projectId: string;
    resourceId: string | null;
  } | null;
}

function toDemandRequirementFillResult(
  result: Awaited<ReturnType<typeof fillDemandRequirement>>,
): FillOpenDemandResult {
  return {
    strategy: "demand_requirement",
    createdAllocation: {
      id: result.assignment.id,
      projectId: result.assignment.projectId,
      resourceId: result.assignment.resourceId,
    },
    updatedAllocation: {
      id: result.updatedDemandRequirement.id,
      projectId: result.updatedDemandRequirement.projectId,
      resourceId: null,
    },
  };
}

export async function fillOpenDemand(
  db: PrismaClient,
  input: FillOpenDemandByAllocationInput,
): Promise<FillOpenDemandResult> {
  const allocation = await loadAllocationEntry(db, input.allocationId);

  if (allocation.kind === "assignment") {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: "Allocation is already filled",
    });
  }

  if (allocation.kind === "demand") {
    const result = await fillDemandRequirement(db, {
      demandRequirementId: allocation.demandRequirement.id,
      resourceId: input.resourceId,
      ...(input.hoursPerDay !== undefined ? { hoursPerDay: input.hoursPerDay } : {}),
      ...(input.status !== undefined ? { status: input.status } : {}),
    });

    return toDemandRequirementFillResult(result);
  }

  throw new TRPCError({
    code: "INTERNAL_SERVER_ERROR",
    message: "Unsupported allocation entry resolution",
  });
}
