import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/core";
import type { Transaction } from "../generated/kysely-tailordb";
import {
  DuplicateLabelNameError,
  InvalidNameError,
  PipelineArchivedError,
  PipelineNotFoundError,
} from "../lib/errors.generated";

export interface CreatePipelineLabelInput {
  pipelineId: string;
  name: string;
  color?: string;
  description?: string;
}

const LABEL_OWN_KEYS = new Set(["pipelineId", "name", "color", "description"]);

export async function run<CF extends Record<string, unknown>>(
  db: Transaction,
  input: CreatePipelineLabelInput & CF,
  ctx: CommandContext,
) {
  void ctx;

  // Consumer extension fields (declared via defineModule's pipelineLabel.fields)
  // pass through to the insert untouched.
  const customFields: Record<string, unknown> = {};
  for (const [key, value] of Object.entries(input as Record<string, unknown>)) {
    if (!LABEL_OWN_KEYS.has(key)) {
      customFields[key] = value;
    }
  }

  const pipeline = await db
    .selectFrom("Pipeline")
    .selectAll()
    .where("id", "=", input.pipelineId)
    .executeTakeFirst();

  if (!pipeline) {
    return err(new PipelineNotFoundError(input.pipelineId));
  }

  if (pipeline.status !== "ACTIVE") {
    return err(new PipelineArchivedError(input.pipelineId));
  }

  if (!input.name.trim()) {
    return err(new InvalidNameError(input.name));
  }

  const duplicate = await db
    .selectFrom("PipelineLabel")
    .selectAll()
    .where("pipelineId", "=", input.pipelineId)
    .where("name", "=", input.name)
    .executeTakeFirst();

  if (duplicate) {
    return err(new DuplicateLabelNameError(input.name));
  }

  const label = await db
    .insertInto("PipelineLabel")
    .values({
      ...customFields,
      pipelineId: input.pipelineId,
      name: input.name,
      color: input.color ?? null,
      description: input.description ?? null,
      createdAt: new Date(),
      updatedAt: null,
    })
    .returningAll()
    .executeTakeFirstOrThrow();

  return ok({ label });
}
