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

export type UpdateProfitCenterInput = { profitCenterId: string } & {
  name?: string;
  description?: string | null;
  responsiblePersonId?: string | null;
  validFrom?: Date;
  validTo?: Date | null;
};
export async function run(db: Transaction, input: UpdateProfitCenterInput, ctx: CommandContext) {
  void ctx;

  // Validate profit center exists
  const profitCenter = await db
    .selectFrom("ProfitCenter")
    .selectAll()
    .where("id", "=", input.profitCenterId)
    .forUpdate()
    .executeTakeFirst();

  if (!profitCenter) {
    return err(new ProfitCenterNotFoundError(input.profitCenterId));
  }

  // Validate status is DRAFT or ACTIVE
  if (!["DRAFT", "ACTIVE"].includes(profitCenter.status)) {
    return err(new InvalidStateError(profitCenter.id));
  }

  // In ACTIVE status, only description and responsiblePersonId can be updated
  if (profitCenter.status === "ACTIVE") {
    const restrictedFields: (keyof UpdateProfitCenterInput)[] = ["name", "validFrom", "validTo"];
    for (const field of restrictedFields) {
      if (input[field] !== undefined) {
        return err(new FieldNotUpdatableError(profitCenter.id));
      }
    }
  }

  // Determine the effective validFrom and validTo for validation
  const effectiveValidFrom = input.validFrom ?? profitCenter.validFrom;
  const effectiveValidTo = input.validTo !== undefined ? input.validTo : profitCenter.validTo;

  // Validate validTo >= validFrom when both are set
  if (effectiveValidTo && effectiveValidFrom && effectiveValidTo < effectiveValidFrom) {
    return err(new InvalidValidityPeriodError(profitCenter.id));
  }

  // Build the update set
  const updateSet: Record<string, unknown> = { updatedAt: new Date() };
  if (input.name !== undefined) updateSet.name = input.name;
  if (input.description !== undefined) updateSet.description = input.description;
  if (input.responsiblePersonId !== undefined)
    updateSet.responsiblePersonId = input.responsiblePersonId;
  if (input.validFrom !== undefined) updateSet.validFrom = input.validFrom;
  if (input.validTo !== undefined) updateSet.validTo = input.validTo;

  const updated = await db
    .updateTable("ProfitCenter")
    .set(updateSet)
    .where("id", "=", profitCenter.id)
    .returningAll()
    .executeTakeFirst();

  return ok({ profitCenter: updated! });
}
