import type { PurchaseCalculatedTotals, PurchaseCreateCommand, PurchasePostingStatus, TaxRateResolver } from './purchase.model';

export type PurchaseWorkflowStatus = 'active' | 'received' | 'cancelled';

export function normalizePurchasePostingStatus(postingType?: 'draft' | 'saved' | 'posted'): PurchasePostingStatus {
  if (postingType === 'draft' || postingType === 'saved') return postingType;
  return 'posted';
}

export function getPurchasePostingStatusLabel(status: PurchasePostingStatus): string {
  if (status === 'draft') return 'مسودة';
  if (status === 'saved') return 'محفوظ';
  return 'مرحل';
}

export function canTransitionPostingStatus(from: PurchasePostingStatus, to: PurchasePostingStatus): boolean {
  if (from === 'posted' && to !== 'posted') return false;
  return true;
}

export function canTransitionWorkflowStatus(from: PurchaseWorkflowStatus, to: PurchaseWorkflowStatus): boolean {
  if (from === 'cancelled') return false;
  if (from === 'active' && (to === 'received' || to === 'cancelled' || to === 'active')) return true;
  if (from === 'received' && (to === 'received' || to === 'cancelled')) return true;
  return false;
}

export function calculatePurchaseTotals(
  command: PurchaseCreateCommand,
  resolveTaxRate: TaxRateResolver
): PurchaseCalculatedTotals {
  let calculatedTaxAmount = 0;
  let lineDiscountTotal = 0;

  const processedItems = command.items.map((item) => {
    const lineSubtotal = Number(item.quantity || 0) * Number(item.unitPrice || 0);
    const percentDiscount = Number(item.lineDiscountPercent || 0);
    const amountDiscount = Number(item.lineDiscountAmount || 0);
    const discountFromPercent = percentDiscount > 0 ? (lineSubtotal * percentDiscount) / 100 : 0;
    const lineDiscount = Math.min(lineSubtotal, discountFromPercent > 0 ? discountFromPercent : amountDiscount);
    const lineTotal = Math.max(0, lineSubtotal - lineDiscount);

    let itemTaxRate = 0;
    let itemTaxAmount = 0;

    if (command.taxMethod === 'line-level') {
      itemTaxRate = item.taxRate !== undefined && item.taxRate > 0 ? item.taxRate : resolveTaxRate(item.materialId);
      itemTaxAmount = (lineTotal * itemTaxRate) / 100;
      calculatedTaxAmount += itemTaxAmount;
    }

    lineDiscountTotal += lineDiscount;

    return {
      materialId: item.materialId,
      name: item.name,
      quantity: item.quantity,
      unitPrice: item.unitPrice,
      total: lineTotal,
      lineDiscountPercent: percentDiscount || undefined,
      lineDiscountAmount: amountDiscount || undefined,
      lineDiscount: lineDiscount > 0 ? lineDiscount : undefined,
      bonus: item.bonus ?? 0,
      warehouseId: (item.warehouseId || '').trim() || undefined,
      shelfId: (item.shelfId || '').trim() || undefined,
      taxRate: itemTaxRate || undefined,
      taxAmount: itemTaxAmount > 0 ? itemTaxAmount : undefined,
      realEstateProjectId: String(item.realEstateProjectId || '').trim() || undefined,
      realEstateProjectName: String(item.realEstateProjectName || '').trim() || undefined,
      realEstateScope: item.realEstateScope || undefined,
      realEstateFloorLabel: String(item.realEstateFloorLabel || '').trim() || undefined,
      realEstatePartLabel: String(item.realEstatePartLabel || '').trim() || undefined,
      realEstateAllocationMethod: item.realEstateScope === 'project'
        ? ((item.realEstateAllocationMethod || command.realEstateAllocationMethod || 'area') as 'area' | 'sale-value' | 'manual-share')
        : undefined,
    };
  });

  const subTotal = processedItems.reduce((sum, item) => sum + Number(item.total || 0), 0);
  const invoiceDiscountFromPercent =
    command.invoiceDiscountPercent > 0 ? (subTotal * command.invoiceDiscountPercent) / 100 : 0;
  const invoiceDiscount = Math.min(
    subTotal,
    invoiceDiscountFromPercent > 0 ? invoiceDiscountFromPercent : Number(command.invoiceDiscountAmount || 0)
  );
  const discountedSubTotal = Math.max(0, subTotal - invoiceDiscount);
  const totalDiscount = lineDiscountTotal + invoiceDiscount;

  if (command.taxMethod === 'invoice-level') {
    calculatedTaxAmount = (discountedSubTotal * command.invoiceTaxRate) / 100;
  }

  if (command.taxMethod === 'tax-inclusive' || command.taxMethod === 'tax-exempt') {
    calculatedTaxAmount = 0;
  }

  const grandTotal = discountedSubTotal + calculatedTaxAmount;
  const amountDue = Math.max(0, grandTotal - command.amountPaid);

  return {
    processedItems,
    subTotal,
    discountedSubTotal,
    lineDiscountTotal,
    invoiceDiscountAmount: invoiceDiscount,
    totalDiscount,
    taxAmount: calculatedTaxAmount,
    grandTotal,
    amountDue,
  };
}
