import {
  DispoStagedRecordType,
  ImportBatchStatus,
  StagedRecordStatus,
} from "@capakraken/db";
import {
  assessDispoImportReadiness,
  stageDispoImportBatch as stageDispoImportBatchApplication,
} from "@capakraken/application";
import { z } from "zod";
import type { TRPCContext } from "../trpc.js";
import {
  cancelImportBatch as cancelImportBatchMutation,
  commitImportBatch as commitImportBatchMutation,
  resolveStagedRecord as resolveStagedRecordMutation,
} from "./dispo-management.js";
import {
  getImportBatch as getImportBatchQuery,
  listImportBatches as listImportBatchesQuery,
  listStagedAssignments as listStagedAssignmentsQuery,
  listStagedProjects as listStagedProjectsQuery,
  listStagedResources as listStagedResourcesQuery,
  listStagedUnresolvedRecords as listStagedUnresolvedRecordsQuery,
  listStagedVacations as listStagedVacationsQuery,
} from "./dispo-read.js";

type DispoProcedureContext = Pick<TRPCContext, "db" | "dbUser">;

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.",
  });

export const stageImportBatchInputSchema = z.object({
  chargeabilityWorkbookPath: workbookPathSchema,
  costWorkbookPath: workbookPathSchema.optional(),
  notes: z.string().nullish(),
  planningWorkbookPath: workbookPathSchema,
  referenceWorkbookPath: workbookPathSchema,
  rosterWorkbookPath: workbookPathSchema.optional(),
});

export const validateImportBatchInputSchema = z.object({
  chargeabilityWorkbookPath: workbookPathSchema,
  costWorkbookPath: workbookPathSchema.optional(),
  importBatchId: z.string().optional(),
  notes: z.string().nullish(),
  planningWorkbookPath: workbookPathSchema,
  referenceWorkbookPath: workbookPathSchema,
  rosterWorkbookPath: workbookPathSchema.optional(),
});

export const listImportBatchesInputSchema = paginationSchema.extend({
  status: importBatchStatusSchema.optional(),
});

export const importBatchIdInputSchema = z.object({
  id: z.string(),
});

export const listStagedResourcesInputSchema = paginationSchema.extend({
  importBatchId: z.string(),
  status: stagedRecordStatusSchema.optional(),
});

export const listStagedProjectsInputSchema = paginationSchema.extend({
  importBatchId: z.string(),
  isTbd: z.boolean().optional(),
  status: stagedRecordStatusSchema.optional(),
});

export const listStagedAssignmentsInputSchema = paginationSchema.extend({
  importBatchId: z.string(),
  resourceExternalId: z.string().optional(),
  status: stagedRecordStatusSchema.optional(),
});

export const listStagedVacationsInputSchema = paginationSchema.extend({
  importBatchId: z.string(),
  resourceExternalId: z.string().optional(),
});

export const listStagedUnresolvedRecordsInputSchema = paginationSchema.extend({
  importBatchId: z.string(),
  recordType: stagedRecordTypeSchema.optional(),
});

export const resolveStagedRecordInputSchema = z.object({
  action: z.enum(["APPROVE", "REJECT", "SKIP"]),
  id: z.string(),
  recordType: stagedRecordTypeSchema,
});

export const commitImportBatchInputSchema = z.object({
  allowTbdUnresolved: z.boolean().optional(),
  importBatchId: z.string(),
  importTbdProjects: z.boolean().optional(),
});

type StageImportBatchInput = z.infer<typeof stageImportBatchInputSchema>;
type ValidateImportBatchInput = z.infer<typeof validateImportBatchInputSchema>;
type ListImportBatchesInput = z.infer<typeof listImportBatchesInputSchema>;
type ImportBatchIdInput = z.infer<typeof importBatchIdInputSchema>;
type ListStagedResourcesInput = z.infer<typeof listStagedResourcesInputSchema>;
type ListStagedProjectsInput = z.infer<typeof listStagedProjectsInputSchema>;
type ListStagedAssignmentsInput = z.infer<typeof listStagedAssignmentsInputSchema>;
type ListStagedVacationsInput = z.infer<typeof listStagedVacationsInputSchema>;
type ListStagedUnresolvedRecordsInput = z.infer<typeof listStagedUnresolvedRecordsInputSchema>;
type ResolveStagedRecordInput = z.infer<typeof resolveStagedRecordInputSchema>;
type CommitImportBatchInput = z.infer<typeof commitImportBatchInputSchema>;

export async function stageImportBatch(
  ctx: DispoProcedureContext,
  input: StageImportBatchInput,
) {
  return stageDispoImportBatchApplication(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 } : {}),
  });
}

export async function validateImportBatch(input: ValidateImportBatchInput) {
  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 } : {}),
  });
}

export async function listImportBatches(ctx: DispoProcedureContext, input: ListImportBatchesInput) {
  return listImportBatchesQuery(ctx.db, input);
}

export async function getImportBatch(ctx: DispoProcedureContext, input: ImportBatchIdInput) {
  return getImportBatchQuery(ctx.db, input.id);
}

export async function cancelImportBatch(ctx: DispoProcedureContext, input: ImportBatchIdInput) {
  return cancelImportBatchMutation(ctx.db, { id: input.id, userId: ctx.dbUser?.id });
}

export async function listStagedResources(
  ctx: DispoProcedureContext,
  input: ListStagedResourcesInput,
) {
  return listStagedResourcesQuery(ctx.db, input);
}

export async function listStagedProjects(
  ctx: DispoProcedureContext,
  input: ListStagedProjectsInput,
) {
  return listStagedProjectsQuery(ctx.db, input);
}

export async function listStagedAssignments(
  ctx: DispoProcedureContext,
  input: ListStagedAssignmentsInput,
) {
  return listStagedAssignmentsQuery(ctx.db, input);
}

export async function listStagedVacations(
  ctx: DispoProcedureContext,
  input: ListStagedVacationsInput,
) {
  return listStagedVacationsQuery(ctx.db, input);
}

export async function listStagedUnresolvedRecords(
  ctx: DispoProcedureContext,
  input: ListStagedUnresolvedRecordsInput,
) {
  return listStagedUnresolvedRecordsQuery(ctx.db, input);
}

export async function resolveStagedRecord(
  ctx: DispoProcedureContext,
  input: ResolveStagedRecordInput,
) {
  return resolveStagedRecordMutation(ctx.db, input);
}

export async function commitImportBatch(
  ctx: DispoProcedureContext,
  input: CommitImportBatchInput,
) {
  return commitImportBatchMutation(ctx.db, {
    importBatchId: input.importBatchId,
    allowTbdUnresolved: input.allowTbdUnresolved,
    importTbdProjects: input.importTbdProjects,
    userId: ctx.dbUser?.id,
  });
}
