import { listAssignmentBookings } from "@capakraken/application";
import { ProjectStatus } from "@capakraken/shared";
import { z } from "zod";
import { CursorInputSchema, paginateCursor } from "../db/pagination.js";
import { controllerProcedure } from "../trpc.js";

export const projectCostReadProcedures = {
  listWithCosts: controllerProcedure
    .input(
      CursorInputSchema.extend({
        status: z.nativeEnum(ProjectStatus).optional(),
        search: z.string().optional(),
      }),
    )
    .query(async ({ ctx, input }) => {
      const { status, search, cursor } = input;
      const where = {
        ...(status ? { status } : {}),
        ...(search
          ? {
              OR: [
                { name: { contains: search, mode: "insensitive" as const } },
                { shortCode: { contains: search, mode: "insensitive" as const } },
              ],
            }
          : {}),
      };
      const whereWithCursor = cursor ? { ...where, id: { gt: cursor } } : where;

      const result = await paginateCursor(
        ({ take }) =>
          ctx.db.project.findMany({
            where: whereWithCursor,
            take,
            orderBy: [{ startDate: "asc" }, { id: "asc" }],
          }),
        input,
      );

      const projectIds = result.items.map((project) => project.id);
      const bookings = projectIds.length
        ? await listAssignmentBookings(ctx.db, {
            startDate: new Date("1900-01-01T00:00:00.000Z"),
            endDate: new Date("2100-12-31T23:59:59.999Z"),
            projectIds,
          })
        : [];

      const projects = result.items.map((project) => {
        const projectBookings = bookings.filter((booking) => booking.projectId === project.id);
        let totalCostCents = 0;
        let totalPersonDays = 0;
        for (const booking of projectBookings) {
          const days =
            (new Date(booking.endDate).getTime() - new Date(booking.startDate).getTime()) /
              (1000 * 60 * 60 * 24) +
            1;
          totalCostCents += booking.dailyCostCents * days;
          totalPersonDays += (booking.hoursPerDay * days) / 8;
        }
        const utilizationPercent = project.budgetCents > 0
          ? Math.round((totalCostCents / project.budgetCents) * 100)
          : 0;
        return {
          ...project,
          totalCostCents: Math.round(totalCostCents),
          totalPersonDays: Math.round(totalPersonDays * 10) / 10,
          utilizationPercent,
        };
      });

      return { projects, nextCursor: result.nextCursor };
    }),
};
