import {
  ImportBatchStatus,
  StagedRecordStatus,
  DispoStagedRecordType,
} from "@capakraken/db";
import {
  assessDispoImportReadiness,
  stageDispoImportBatch,
} from "@capakraken/application";
import { z } from "zod";
import { adminProcedure, createTRPCRouter } from "../trpc.js";
import { commitImportBatch, cancelImportBatch, resolveStagedRecord } from "./dispo-management.js";
import {
  getImportBatch,
  listImportBatches,
  listStagedAssignments,
  listStagedProjects,
  listStagedResources,
  listStagedUnresolvedRecords,
  listStagedVacations,
} from "./dispo-read.js";

// ─── Shared schemas ──────────────────────────────────────────────────────────

const paginationSchema = z.object({
  cursor: z.string().optional(),
  limit: z.number().int().min(1).max(200).default(50),
});

const importBatchStatusSchema = z.nativeEnum(ImportBatchStatus);
const stagedRecordStatusSchema = z.nativeEnum(StagedRecordStatus);
const stagedRecordTypeSchema = z.nativeEnum(DispoStagedRecordType);
const workbookPathSchema = z
  .string()
  .trim()
  .min(1, "Workbook path is required.")
  .refine((value) => value.toLowerCase().endsWith(".xlsx"), {
    message: "Only .xlsx workbook paths are supported.",
  });

// ─── Router ──────────────────────────────────────────────────────────────────

export const dispoRouter = createTRPCRouter({
  // ── 1. stageImportBatch ──────────────────────────────────────────────────

  stageImportBatch: adminProcedure
    .input(
      z.object({
        chargeabilityWorkbookPath: workbookPathSchema,
        costWorkbookPath: workbookPathSchema.optional(),
        notes: z.string().nullish(),
        planningWorkbookPath: workbookPathSchema,
        referenceWorkbookPath: workbookPathSchema,
        rosterWorkbookPath: workbookPathSchema.optional(),
      }),
    )
    .mutation(async ({ ctx, input }) => {
      return stageDispoImportBatch(ctx.db, {
        chargeabilityWorkbookPath: input.chargeabilityWorkbookPath,
        planningWorkbookPath: input.planningWorkbookPath,
        referenceWorkbookPath: input.referenceWorkbookPath,
        ...(input.costWorkbookPath !== undefined ? { costWorkbookPath: input.costWorkbookPath } : {}),
        ...(input.notes !== undefined ? { notes: input.notes } : {}),
        ...(input.rosterWorkbookPath !== undefined ? { rosterWorkbookPath: input.rosterWorkbookPath } : {}),
      });
    }),

  // ── 2. validateImportBatch ───────────────────────────────────────────────

  validateImportBatch: adminProcedure
    .input(
      z.object({
        chargeabilityWorkbookPath: workbookPathSchema,
        costWorkbookPath: workbookPathSchema.optional(),
        importBatchId: z.string().optional(),
        notes: z.string().nullish(),
        planningWorkbookPath: workbookPathSchema,
        referenceWorkbookPath: workbookPathSchema,
        rosterWorkbookPath: workbookPathSchema.optional(),
      }),
    )
    .query(async ({ input }) => {
      return assessDispoImportReadiness({
        chargeabilityWorkbookPath: input.chargeabilityWorkbookPath,
        planningWorkbookPath: input.planningWorkbookPath,
        referenceWorkbookPath: input.referenceWorkbookPath,
        ...(input.costWorkbookPath !== undefined ? { costWorkbookPath: input.costWorkbookPath } : {}),
        ...(input.importBatchId !== undefined ? { importBatchId: input.importBatchId } : {}),
        ...(input.notes !== undefined ? { notes: input.notes } : {}),
        ...(input.rosterWorkbookPath !== undefined ? { rosterWorkbookPath: input.rosterWorkbookPath } : {}),
      });
    }),

  // ── 3. listImportBatches ─────────────────────────────────────────────────

  listImportBatches: adminProcedure
    .input(
      paginationSchema.extend({
        status: importBatchStatusSchema.optional(),
      }),
    )
    .query(async ({ ctx, input }) => {
      return listImportBatches(ctx.db, input);
    }),

  // ── 4. getImportBatch ────────────────────────────────────────────────────

  getImportBatch: adminProcedure
    .input(z.object({ id: z.string() }))
    .query(async ({ ctx, input }) => {
      return getImportBatch(ctx.db, input.id);
    }),

  // ── 5. cancelImportBatch ─────────────────────────────────────────────────

  cancelImportBatch: adminProcedure
    .input(z.object({ id: z.string() }))
    .mutation(async ({ ctx, input }) => {
      return cancelImportBatch(ctx.db, { id: input.id, userId: ctx.dbUser?.id });
    }),

  // ── 6. listStagedResources ───────────────────────────────────────────────

  listStagedResources: adminProcedure
    .input(
      paginationSchema.extend({
        importBatchId: z.string(),
        status: stagedRecordStatusSchema.optional(),
      }),
    )
    .query(async ({ ctx, input }) => {
      return listStagedResources(ctx.db, input);
    }),

  // ── 7. listStagedProjects ────────────────────────────────────────────────

  listStagedProjects: adminProcedure
    .input(
      paginationSchema.extend({
        importBatchId: z.string(),
        isTbd: z.boolean().optional(),
        status: stagedRecordStatusSchema.optional(),
      }),
    )
    .query(async ({ ctx, input }) => {
      return listStagedProjects(ctx.db, input);
    }),

  // ── 8. listStagedAssignments ─────────────────────────────────────────────

  listStagedAssignments: adminProcedure
    .input(
      paginationSchema.extend({
        importBatchId: z.string(),
        resourceExternalId: z.string().optional(),
        status: stagedRecordStatusSchema.optional(),
      }),
    )
    .query(async ({ ctx, input }) => {
      return listStagedAssignments(ctx.db, input);
    }),

  // ── 9. listStagedVacations ───────────────────────────────────────────────

  listStagedVacations: adminProcedure
    .input(
      paginationSchema.extend({
        importBatchId: z.string(),
        resourceExternalId: z.string().optional(),
      }),
    )
    .query(async ({ ctx, input }) => {
      return listStagedVacations(ctx.db, input);
    }),

  // ── 10. listStagedUnresolvedRecords ──────────────────────────────────────

  listStagedUnresolvedRecords: adminProcedure
    .input(
      paginationSchema.extend({
        importBatchId: z.string(),
        recordType: stagedRecordTypeSchema.optional(),
      }),
    )
    .query(async ({ ctx, input }) => {
      return listStagedUnresolvedRecords(ctx.db, input);
    }),

  // ── 11. resolveStagedRecord ──────────────────────────────────────────────

  resolveStagedRecord: adminProcedure
    .input(
      z.object({
        action: z.enum(["APPROVE", "REJECT", "SKIP"]),
        id: z.string(),
        recordType: stagedRecordTypeSchema,
      }),
    )
    .mutation(async ({ ctx, input }) => {
      return resolveStagedRecord(ctx.db, input);
    }),

  // ── 12. commitImportBatch ────────────────────────────────────────────────

  commitImportBatch: adminProcedure
    .input(
      z.object({
        allowTbdUnresolved: z.boolean().optional(),
        importBatchId: z.string(),
        importTbdProjects: z.boolean().optional(),
      }),
    )
    .mutation(async ({ ctx, input }) => {
      return commitImportBatch(ctx.db, {
        importBatchId: input.importBatchId,
        allowTbdUnresolved: input.allowTbdUnresolved,
        importTbdProjects: input.importTbdProjects,
        userId: ctx.dbUser?.id,
      });
    }),
});
