import type { Transaction } from "../generated/kysely-tailordb";
import {
  CostCenterNotFoundError,
  InvalidCategoryError,
  InvalidValidityPeriodError,
  InvalidNameError,
} from "../lib/errors.generated";
import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/module";

const VALID_CATEGORIES = ["overhead", "production", "administration", "sales", "research"];

export type UpdateCostCenterInput = {
  costCenterId: string;
  name?: string;
  description?: string | null;
  category?: string;
  responsiblePersonId?: string | null;
  departmentId?: string | null;
  validFrom?: Date;
  validTo?: Date | null;
};

export async function run(db: Transaction, input: UpdateCostCenterInput, ctx: CommandContext) {
  void ctx;

  const { name, description, category, responsiblePersonId, departmentId, validFrom, validTo } =
    input;

  // Validate cost center exists
  const costCenter = await db
    .selectFrom("CostCenter")
    .where("id", "=", input.costCenterId)
    .selectAll()
    .forUpdate()
    .executeTakeFirst();

  if (!costCenter) {
    return err(new CostCenterNotFoundError(input.costCenterId));
  }

  // Validate name if provided
  if (name !== undefined && (!name || name.trim() === "")) {
    return err(new InvalidNameError(costCenter.id));
  }

  // Validate category if provided
  if (category !== undefined && !VALID_CATEGORIES.includes(category)) {
    return err(new InvalidCategoryError(category));
  }

  // Validate validity dates
  const newValidFrom = validFrom ?? costCenter.validFrom;
  const newValidTo = validTo !== undefined ? validTo : costCenter.validTo;
  if (newValidTo && newValidFrom > newValidTo) {
    return err(new InvalidValidityPeriodError(costCenter.id));
  }

  // Build update set
  const updateSet: Record<string, unknown> = {
    updatedAt: new Date(),
  };

  if (name !== undefined) updateSet.name = name;
  if (description !== undefined) updateSet.description = description;
  if (category !== undefined) updateSet.category = category;
  if (responsiblePersonId !== undefined) updateSet.responsiblePersonId = responsiblePersonId;
  if (departmentId !== undefined) updateSet.departmentId = departmentId;
  if (validFrom !== undefined) updateSet.validFrom = validFrom;
  if (validTo !== undefined) updateSet.validTo = validTo;

  const updatedCostCenter = await db
    .updateTable("CostCenter")
    .set(updateSet)
    .where("id", "=", costCenter.id)
    .returningAll()
    .executeTakeFirst();

  return ok({ costCenter: updatedCostCenter! });
}
