import type { Transaction } from "../generated/kysely-tailordb";
import {
  InvalidEffectiveRangeError,
  InvalidUnitPriceError,
  PriceListNotFoundError,
  SalespriceruleNotEditableError,
  SalespriceruleNotFoundError,
} from "../lib/errors.generated";
import { err, ok, type CommandContext } from "@tailor-platform/erp-kit/module";

export type UpdateSalesPriceRuleInput = {
  salesPriceRuleId: string;
  salesPriceListId?: string;
  customerId?: string | null;
  channelId?: string | null;
  currencyId?: string;
  unitId?: string;
  minimumQuantity?: number;
  unitPrice?: number;
  effectiveFrom?: Date | null;
  effectiveTo?: Date | null;
  priority?: number;
  notes?: string | null;
};
export async function run(db: Transaction, input: UpdateSalesPriceRuleInput, ctx: CommandContext) {
  void ctx;
  const salesPriceRule = await db
    .selectFrom("SalesPriceRule")
    .selectAll()
    .where("id", "=", input.salesPriceRuleId)
    .forUpdate()
    .executeTakeFirst();
  if (!salesPriceRule) {
    return err(new SalespriceruleNotFoundError(input.salesPriceRuleId));
  }
  if (!["DRAFT", "ACTIVE"].includes(salesPriceRule.status)) {
    return err(new SalespriceruleNotEditableError(input.salesPriceRuleId));
  }
  const salesPriceListId = input.salesPriceListId ?? salesPriceRule.salesPriceListId;
  const salesPriceList = await db
    .selectFrom("SalesPriceList")
    .selectAll()
    .where("id", "=", salesPriceListId)
    .executeTakeFirst();
  if (!salesPriceList) {
    return err(new PriceListNotFoundError(salesPriceListId));
  }
  const unitPrice = input.unitPrice ?? salesPriceRule.unitPrice;
  const minimumQuantity = input.minimumQuantity ?? salesPriceRule.minimumQuantity;
  const effectiveFrom =
    input.effectiveFrom === undefined ? salesPriceRule.effectiveFrom : input.effectiveFrom;
  const effectiveTo =
    input.effectiveTo === undefined ? salesPriceRule.effectiveTo : input.effectiveTo;
  if (unitPrice <= 0 || minimumQuantity < 0) {
    return err(new InvalidUnitPriceError(input.salesPriceRuleId));
  }
  if (effectiveFrom && effectiveTo && effectiveTo < effectiveFrom) {
    return err(new InvalidEffectiveRangeError(input.salesPriceRuleId));
  }
  const updated = await db
    .updateTable("SalesPriceRule")
    .set({
      salesPriceListId,
      customerId: input.customerId === undefined ? salesPriceRule.customerId : input.customerId,
      channelId: input.channelId === undefined ? salesPriceRule.channelId : input.channelId,
      currencyId: input.currencyId ?? salesPriceRule.currencyId,
      unitId: input.unitId ?? salesPriceRule.unitId,
      minimumQuantity,
      unitPrice,
      effectiveFrom,
      effectiveTo,
      priority: input.priority ?? salesPriceRule.priority,
      notes: input.notes === undefined ? salesPriceRule.notes : input.notes,
      updatedAt: new Date(),
    })
    .where("id", "=", input.salesPriceRuleId)
    .returningAll()
    .executeTakeFirst();
  return ok({ salesPriceRule: updated! });
}
