import {
  type CommonReservedFields,
  type NoReservedFields,
  defaultGqlPermission,
  defaultPermission,
} from "@tailor-platform/erp-kit/core";
import { db, type TailorAnyDBField } from "@tailor-platform/sdk";
import { pipeline } from "./pipeline";

export const STAGE_CATEGORIES = ["NOT_STARTED", "IN_PROGRESS", "DONE", "CANCELED"] as const;
export type StageCategory = (typeof STAGE_CATEGORIES)[number];
export function isStageCategory(value: string): value is StageCategory {
  return STAGE_CATEGORIES.some((c) => c === value);
}

const builtins = () => ({
  pipelineId: db
    .uuid()
    .relation({
      type: "n-1",
      toward: { type: pipeline },
      backward: "stages",
    })
    .description("ID of the pipeline this stage belongs to"),
  name: db.string().description("PipelineStage name (e.g. 'To Do', 'In Progress', 'Done')"),
  position: db.int().description("Display order within the pipeline (1-based, left to right)"),
  category: db
    .enum(STAGE_CATEGORIES)
    .description(
      "Semantic category of the stage. NOT_STARTED = not yet started, IN_PROGRESS = being worked on, DONE = completed, CANCELED = canceled",
    ),
  color: db.string({ optional: true }).description("Color code for UI display (e.g. '#3B82F6')"),
});

type ReservedFields = keyof ReturnType<typeof builtins> | CommonReservedFields;

export interface CreatePipelineStageTypeParams<F extends Record<string, TailorAnyDBField>> {
  fields?: NoReservedFields<F, ReservedFields>;
}

export function createPipelineStageType<const F extends Record<string, TailorAnyDBField>>(
  params: CreatePipelineStageTypeParams<F> = {},
) {
  return db
    .type("PipelineStage", {
      ...builtins(),
      // oxlint-disable-next-line typescript/no-unsafe-type-assertion -- mirrors erp-kit's createXxxType factories; field bag is constrained but TS can't prove F is concrete
      ...((params.fields ?? {}) as F),
      ...db.fields.timestamps(),
    })
    .description(
      "Pipeline stage. Corresponds to a kanban column within a Pipeline; items move between stages to represent progress. " +
        "Duplicate names per pipeline are prevented by a unique index, with a friendly duplicate check in the create/update commands.",
    )
    .indexes({
      fields: ["pipelineId", "name"],
      unique: true,
      name: "stage_pipeline_name_unique_idx",
    })
    .permission(defaultPermission)
    .gqlPermission(defaultGqlPermission);
}

export const pipelineStage = createPipelineStageType({});
