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

export interface CalculateInvoiceDueScheduleInput {
  paymentTermId: string;
  invoiceDate: Date;
  invoiceAmount?: number;
}

export async function run(db: ReadonlyDB<DB>, input: CalculateInvoiceDueScheduleInput) {
  const paymentTerm = await db
    .selectFrom("SalesPaymentTerm")
    .selectAll()
    .where("id", "=", input.paymentTermId)
    .executeTakeFirst();
  if (!paymentTerm) {
    return err(new PaymentTermNotFoundError(input.paymentTermId));
  }

  const dueSchedule = calculateDueSchedule(
    decodeJson<PaymentTermScheduleLineInput[]>(paymentTerm.scheduleLines, []),
    input.invoiceDate,
    input.invoiceAmount ?? 0,
  );
  if (!dueSchedule) {
    return err(new InvalidPaymentTermDefinitionError(input.paymentTermId));
  }

  return ok({ dueSchedule });
}
