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

export type UpdateInternalOrderInput = {
  internalOrderId: string;
  description?: string;
  responsiblePersonId?: string;
  costCenterId?: string;
  orderType?: string;
  validFrom?: Date | null;
  validTo?: Date | null;
};
export async function run(db: Transaction, input: UpdateInternalOrderInput, ctx: CommandContext) {
  void ctx;

  // Fetch internal order
  const order = await db
    .selectFrom("InternalOrder")
    .selectAll()
    .where("id", "=", input.internalOrderId)
    .forUpdate()
    .executeTakeFirst();

  if (!order) {
    return err(new InternalOrderNotFoundError(input.internalOrderId));
  }

  // Validate status allows update
  if (!["CREATED", "RELEASED"].includes(order.status)) {
    return err(new InvalidStateError(input.internalOrderId));
  }

  // Order type cannot change after release
  if (
    input.orderType !== undefined &&
    order.status === "RELEASED" &&
    input.orderType !== order.orderType
  ) {
    return err(new OrderTypeChangeNotAllowedError(input.internalOrderId));
  }

  // Validate cost center if changed
  if (input.costCenterId !== undefined) {
    const costCenter = await db
      .selectFrom("CostCenter")
      .where("id", "=", input.costCenterId)
      .where("companyId", "=", order.companyId)
      .selectAll()
      .executeTakeFirst();

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

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

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

  const updated = await db
    .updateTable("InternalOrder")
    .set(updates)
    .where("id", "=", input.internalOrderId)
    .returningAll()
    .executeTakeFirst();

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