import { prisma } from "./prisma";
import { getI18n } from "./i18n/server";

export const DEFAULT_WINDOW = { minQty: 1, maxQty: 9999 };

export function basePrice(product: {
  retailPrice: number;
  semiWholesalePrice: number;
  wholesalePrice: number;
}, accountType: string) {
  if (accountType === "WHOLESALE") return product.wholesalePrice;
  if (accountType === "SEMI_WHOLESALE") return product.semiWholesalePrice;
  return product.retailPrice;
}

/**
 * Unit price for a customer's account type. The price depends only on the account type;
 * the quantity must sit inside that account type's min / max window for the product.
 */
export async function unitPriceFor(productId: string, accountType: string, quantity: number) {
  const { t, label } = await getI18n();
  const product = await prisma.product.findUnique({ where: { id: productId } });
  if (!product) throw new Error(t("Product not found"));
  const list = await prisma.priceList.findUnique({
    where: { productId_accountType: { productId, accountType } },
  });
  if (list && !list.active) {
    throw new Error(t("{product} is not sold to {type} accounts.", { product: product.name, type: label(accountType) }));
  }
  const { minQty, maxQty } = list ?? DEFAULT_WINDOW;
  if (quantity < minQty || quantity > maxQty) {
    throw new Error(
      t("{product}: quantity for {type} must be between {min} and {max}.", {
        product: product.name,
        type: label(accountType),
        min: minQty,
        max: maxQty,
      }),
    );
  }
  return basePrice(product, accountType);
}

/** Catalog as the order forms need it: price and quantity window per account type. */
export async function catalogForForms() {
  const products = await prisma.product.findMany({
    where: { active: true },
    include: { priceLists: true },
    orderBy: { name: "asc" },
  });
  return products.map((product) => ({
    id: product.id,
    name: product.name,
    stock: product.quantity,
    rules: Object.fromEntries(
      (["RETAIL", "SEMI_WHOLESALE", "WHOLESALE"] as const).map((type) => {
        const list = product.priceLists.find((row) => row.accountType === type);
        return [
          type,
          {
            price: basePrice(product, type),
            min: list?.minQty ?? DEFAULT_WINDOW.minQty,
            max: list?.maxQty ?? DEFAULT_WINDOW.maxQty,
            active: list?.active ?? true,
          },
        ];
      }),
    ) as Record<string, { price: number; min: number; max: number; active: boolean }>,
  }));
}

export type CatalogItem = Awaited<ReturnType<typeof catalogForForms>>[number];

export async function customerBalance(customerId: string) {
  const invoiced = await prisma.deliveryNote.aggregate({
    where: { customerId, status: "VALIDATED" },
    _sum: { total: true },
  });
  const paid = await prisma.payment.aggregate({
    where: { customerId },
    _sum: { amount: true },
  });
  const invoicedAmount = invoiced._sum.total ?? 0;
  const paidAmount = paid._sum.amount ?? 0;
  return {
    invoicedAmount,
    paidAmount,
    remaining: invoicedAmount - paidAmount,
  };
}
