import {
  CreateCalculationRuleSchema,
  UpdateCalculationRuleSchema,
} from "@capakraken/shared";
import { z } from "zod";
import { findUniqueOrThrow } from "../db/helpers.js";
import { PROJECT_BRIEF_SELECT } from "../db/selects.js";
import { createTRPCRouter, controllerProcedure, managerProcedure } from "../trpc.js";
import { createAuditEntry } from "../lib/audit.js";
import {
  buildCalculationRuleCreateData,
  buildCalculationRuleUpdateData,
} from "./calculation-rule-support.js";

export const calculationRuleRouter = createTRPCRouter({
  list: controllerProcedure.query(async ({ ctx }) => {
    return ctx.db.calculationRule.findMany({
      orderBy: [{ priority: "desc" }, { name: "asc" }],
      include: { project: { select: PROJECT_BRIEF_SELECT } },
    });
  }),

  getById: controllerProcedure
    .input(z.object({ id: z.string() }))
    .query(async ({ ctx, input }) => {
      return findUniqueOrThrow(
        ctx.db.calculationRule.findUnique({
          where: { id: input.id },
          include: { project: { select: PROJECT_BRIEF_SELECT } },
        }),
        "CalculationRule",
      );
    }),

  /** Get all active rules (optimized for engine use — no project include) */
  getActive: controllerProcedure.query(async ({ ctx }) => {
    return ctx.db.calculationRule.findMany({
      where: { isActive: true },
      orderBy: [{ priority: "desc" }],
    });
  }),

  create: managerProcedure
    .input(CreateCalculationRuleSchema)
    .mutation(async ({ ctx, input }) => {
      const rule = await ctx.db.calculationRule.create({
        data: buildCalculationRuleCreateData(input),
      });

      void createAuditEntry({
        db: ctx.db,
        entityType: "CalculationRule",
        entityId: rule.id,
        entityName: rule.name,
        action: "CREATE",
        userId: ctx.dbUser?.id,
        after: rule as unknown as Record<string, unknown>,
        source: "ui",
      });

      return rule;
    }),

  update: managerProcedure
    .input(UpdateCalculationRuleSchema)
    .mutation(async ({ ctx, input }) => {
      const { id, ...data } = input;
      const before = await findUniqueOrThrow(
        ctx.db.calculationRule.findUnique({ where: { id } }),
        "CalculationRule",
      );

      const updated = await ctx.db.calculationRule.update({
        where: { id },
        data: buildCalculationRuleUpdateData(data),
      });

      void createAuditEntry({
        db: ctx.db,
        entityType: "CalculationRule",
        entityId: id,
        entityName: updated.name,
        action: "UPDATE",
        userId: ctx.dbUser?.id,
        before: before as unknown as Record<string, unknown>,
        after: updated as unknown as Record<string, unknown>,
        source: "ui",
      });

      return updated;
    }),

  delete: managerProcedure
    .input(z.object({ id: z.string() }))
    .mutation(async ({ ctx, input }) => {
      const rule = await findUniqueOrThrow(
        ctx.db.calculationRule.findUnique({ where: { id: input.id } }),
        "CalculationRule",
      );
      await ctx.db.calculationRule.delete({ where: { id: input.id } });

      void createAuditEntry({
        db: ctx.db,
        entityType: "CalculationRule",
        entityId: input.id,
        entityName: rule.name,
        action: "DELETE",
        userId: ctx.dbUser?.id,
        before: rule as unknown as Record<string, unknown>,
        source: "ui",
      });

      return { success: true };
    }),
});
