import type { DB } from "../generated/kysely-tailordb";
import {
  InvalidBillAmountError,
  InvalidPaymentTermConfigurationError,
  PaymentTermNotFoundError,
} from "../lib/errors.generated";
import { buildPaymentTermSnapshot, calculateDueSchedule } from "../lib/domain";
import { err, ok, type ReadonlyDB, type QueryContext } from "@tailor-platform/erp-kit/module";

export interface CalculatePurchaseBillDueScheduleInput {
  purchasePaymentTermId: string;
  billDate: Date;
  billAmount: number;
}

export async function run(
  db: ReadonlyDB<DB>,
  input: CalculatePurchaseBillDueScheduleInput,
  ctx?: QueryContext,
) {
  void ctx;
  const paymentTerm = await db
    .selectFrom("PurchasePaymentTerm")
    .selectAll()
    .where("id", "=", input.purchasePaymentTermId)
    .executeTakeFirst();
  if (!paymentTerm) {
    return err(new PaymentTermNotFoundError(input.purchasePaymentTermId));
  }

  const snapshot = buildPaymentTermSnapshot(paymentTerm);
  const result = calculateDueSchedule(snapshot.lines, input.billDate, input.billAmount);
  if ("error" in result) {
    if (result.error === "INVALID_BILL_AMOUNT") {
      return err(new InvalidBillAmountError(String(input.billAmount)));
    }
    return err(new InvalidPaymentTermConfigurationError(input.purchasePaymentTermId));
  }

  return ok({ dueSchedule: result.schedule, paymentTerm });
}
