import { ProjectStatus } from "@capakraken/shared";
import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { controllerProcedure, planningReadProcedure } from "../trpc.js";
import {
  mapProjectDetail,
  mapProjectSummary,
  mapProjectSummaryDetail,
  readProjectByIdentifierDetailSnapshot,
  readProjectSummariesSnapshot,
  readProjectSummaryDetailsSnapshot,
  resolveProjectIdentifierSnapshot,
} from "./project-read-shared.js";

export const projectIdentifierReadProcedures = {
  resolveByIdentifier: planningReadProcedure
    .input(z.object({ identifier: z.string() }))
    .query(async ({ ctx, input }) => {
      const select = {
        id: true,
        shortCode: true,
        name: true,
        status: true,
        responsiblePerson: true,
        startDate: true,
        endDate: true,
      } as const;

      let project = await ctx.db.project.findUnique({
        where: { id: input.identifier },
        select,
      });
      if (!project) {
        project = await ctx.db.project.findUnique({
          where: { shortCode: input.identifier },
          select,
        });
      }
      if (!project) {
        project = await ctx.db.project.findFirst({
          where: { name: { equals: input.identifier, mode: "insensitive" } },
          select,
        });
      }
      if (!project) {
        project = await ctx.db.project.findFirst({
          where: { name: { contains: input.identifier, mode: "insensitive" } },
          select,
        });
      }

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

      return project;
    }),

  searchSummaries: planningReadProcedure
    .input(z.object({
      search: z.string().optional(),
      status: z.nativeEnum(ProjectStatus).optional(),
      limit: z.number().int().min(1).max(50).default(20),
    }))
    .query(async ({ ctx, input }) => {
      const { items, exactMatch } = await readProjectSummariesSnapshot(ctx, input);
      const formatted = items.map(mapProjectSummary);
      if (items.length > 0 && input.search && !exactMatch) {
        return {
          suggestions: formatted,
          note: `No exact match for "${input.search}". These projects match some of the search terms:`,
        };
      }
      return formatted;
    }),

  searchSummariesDetail: controllerProcedure
    .input(z.object({
      search: z.string().optional(),
      status: z.nativeEnum(ProjectStatus).optional(),
      limit: z.number().int().min(1).max(50).default(20),
    }))
    .query(async ({ ctx, input }) => {
      const { items, exactMatch } = await readProjectSummaryDetailsSnapshot(ctx, input);
      const formatted = items.map(mapProjectSummaryDetail);
      if (items.length > 0 && input.search && !exactMatch) {
        return {
          suggestions: formatted,
          note: `No exact match for "${input.search}". These projects match some of the search terms:`,
        };
      }
      return formatted;
    }),

  getByIdentifier: planningReadProcedure
    .input(z.object({ identifier: z.string() }))
    .query(async ({ ctx, input }) => resolveProjectIdentifierSnapshot(ctx, input.identifier)),

  getByIdentifierDetail: controllerProcedure
    .input(z.object({ identifier: z.string() }))
    .query(async ({ ctx, input }) => {
      const project = await readProjectByIdentifierDetailSnapshot(ctx, input.identifier);
      return mapProjectDetail(project, project.topAssignments);
    }),
};
