import { buildSplitAllocationReadModel } from "@capakraken/application";
import type { PrismaClient } from "@capakraken/db";
import { AllocationStatus } from "@capakraken/shared";
import { ROLE_BRIEF_SELECT } from "../db/selects.js";

export const PROJECT_PLANNING_ALLOCATION_INCLUDE = {
  resource: {
    select: {
      id: true,
      displayName: true,
      eid: true,
      chapter: true,
      lcrCents: true,
      availability: true,
    },
  },
  project: {
    select: {
      id: true,
      name: true,
      shortCode: true,
      orderType: true,
      clientId: true,
      budgetCents: true,
      winProbability: true,
      status: true,
      startDate: true,
      endDate: true,
      staffingReqs: true,
      responsiblePerson: true,
      color: true,
    },
  },
  roleEntity: {
    select: ROLE_BRIEF_SELECT,
  },
} as const;

export const PROJECT_PLANNING_DEMAND_INCLUDE = {
  project: PROJECT_PLANNING_ALLOCATION_INCLUDE.project,
  roleEntity: PROJECT_PLANNING_ALLOCATION_INCLUDE.roleEntity,
} as const;

export const PROJECT_PLANNING_ASSIGNMENT_INCLUDE = {
  resource: PROJECT_PLANNING_ALLOCATION_INCLUDE.resource,
  project: PROJECT_PLANNING_ALLOCATION_INCLUDE.project,
  roleEntity: PROJECT_PLANNING_ALLOCATION_INCLUDE.roleEntity,
} as const;

/**
 * Lighter resource select for timeline rendering (hot path).
 * Omits `availability` which is only needed for budget/cost calculations.
 */
const TIMELINE_RESOURCE_SELECT = {
  select: {
    id: true,
    displayName: true,
    eid: true,
    chapter: true,
    lcrCents: true,
  },
} as const;

export const TIMELINE_ASSIGNMENT_INCLUDE = {
  resource: TIMELINE_RESOURCE_SELECT,
  project: PROJECT_PLANNING_ALLOCATION_INCLUDE.project,
  roleEntity: PROJECT_PLANNING_ALLOCATION_INCLUDE.roleEntity,
} as const;

type ProjectPlanningReadDbClient = Pick<
  PrismaClient,
  "demandRequirement" | "assignment"
>;

export interface LoadProjectPlanningReadModelInput {
  projectId: string;
  activeOnly?: boolean;
}

export async function loadProjectPlanningReadModel(
  db: ProjectPlanningReadDbClient,
  input: LoadProjectPlanningReadModelInput,
) {
  const statusFilter = input.activeOnly
    ? { status: { not: AllocationStatus.CANCELLED } }
    : {};

  const [demandRequirements, assignments] = await Promise.all([
    db.demandRequirement.findMany({
      where: {
        projectId: input.projectId,
        ...statusFilter,
      },
      include: PROJECT_PLANNING_DEMAND_INCLUDE,
      orderBy: [{ startDate: "asc" }, { projectId: "asc" }],
    }),
    db.assignment.findMany({
      where: {
        projectId: input.projectId,
        ...statusFilter,
      },
      include: PROJECT_PLANNING_ASSIGNMENT_INCLUDE,
      orderBy: [{ startDate: "asc" }, { resourceId: "asc" }],
    }),
  ]);

  return {
    demandRequirements,
    assignments,
    readModel: buildSplitAllocationReadModel({
      demandRequirements,
      assignments,
    }),
  };
}
