import { ok, err, type CommandContext } from "@tailor-platform/erp-kit/core";
import { Decimal } from "decimal.js";
import type { ValuationPolicyCostingMethod } from "../generated/enums";
import type { Transaction } from "../generated/kysely-tailordb";
import {
  ValuationPolicyNotFoundError,
  StandardCostRateRequiredError,
} from "../lib/errors.generated";

export type UpdateValuationPolicyInput = {
  id: string;
  name?: string;
  costingMethod?: ValuationPolicyCostingMethod;
  standardCostRate?: number | null;
};
/**
 * Function: updateValuationPolicy
 *
 * Updates an existing valuation policy. When the standardCostRate is changed
 * for a STANDARD_COST policy, a revaluation event is emitted.
 */
export async function run(
  db: Transaction,
  input: UpdateValuationPolicyInput,
  _ctx: CommandContext,
) {
  const { id, name, costingMethod, standardCostRate } = input;

  // 1. Fetch existing policy
  const existing = await db
    .selectFrom("ValuationPolicy")
    .selectAll()
    .where("id", "=", id)
    .forUpdate()
    .executeTakeFirst();

  if (!existing) {
    return err(new ValuationPolicyNotFoundError(id));
  }

  // 2. Determine effective costing method after update
  const effectiveCostingMethod = costingMethod ?? existing.costingMethod;

  // 3. If STANDARD_COST, require standardCostRate
  if (
    effectiveCostingMethod === "STANDARD_COST" &&
    standardCostRate == null &&
    existing.standardCostRate == null
  ) {
    return err(new StandardCostRateRequiredError(id));
  }

  // 4. Update policy
  const updated = await db
    .updateTable("ValuationPolicy")
    .set({
      ...(name !== undefined && { name }),
      ...(costingMethod !== undefined && { costingMethod }),
      ...(standardCostRate !== undefined && {
        standardCostRate: standardCostRate !== null ? String(standardCostRate) : null,
      }),
    })
    .where("id", "=", id)
    .returningAll()
    .executeTakeFirstOrThrow();

  // 5. Check if standard cost rate changed (emit revaluation event)
  const revaluationEvent =
    effectiveCostingMethod === "STANDARD_COST" &&
    standardCostRate != null &&
    (existing.standardCostRate == null ||
      !new Decimal(existing.standardCostRate).eq(standardCostRate));

  return ok({ valuationPolicy: updated, revaluationEvent });
}
