import type { CustomerPayment, InventoryMovement, JournalEntry, SalesInvoice } from '@/lib/types';

// ─── Shared Types ────────────────────────────────────────────────────────────

export type MaterialFull = {
  id: string;
  name: string;
  purchasePrice?: number;
  reorderMinimumQty?: number;
  groupId?: string;
};

export type GroupLite = {
  id: string;
  name: string;
};

export type AdvancedFilters = {
  fromDate?: string;
  toDate?: string;
  customerId?: string;
  materialId?: string;
};

// ─── Row / Result Types ──────────────────────────────────────────────────────

export type ProfitByInvoiceRow = {
  invoiceId: string;
  invoiceNumber: string;
  date: string;
  customerId: string;
  customerName: string;
  salesValue: number;
  estimatedCost: number;
  estimatedProfit: number;
  profitMargin: number;
};

export type CustomerFrequencyRow = {
  customerId: string;
  customerName: string;
  invoiceCount: number;
  totalSales: number;
  firstInvoiceDate: string;
  lastInvoiceDate: string;
  daysSinceLastPurchase: number;
  avgDaysBetweenPurchases: number | null;
};

export type BestSellingTimeRow = {
  dayOfWeek: number; // 0=Sunday … 6=Saturday
  dayNameAr: string;
  invoiceCount: number;
  totalSales: number;
  averageSale: number;
};

export type BranchPerformanceRow = {
  warehouseId: string;
  invoiceCount: number;
  lineCount: number;
  totalQuantity: number;
  totalSales: number;
  estimatedCost: number;
  estimatedProfit: number;
  profitMargin: number;
};

export type CategoryPerformanceRow = {
  groupId: string;
  groupName: string;
  lineCount: number;
  totalQuantity: number;
  totalSales: number;
  estimatedCost: number;
  estimatedProfit: number;
  profitMargin: number;
};

export type CollectionRateRow = {
  customerId: string;
  customerName: string;
  totalBilled: number;
  totalPaid: number;
  totalDue: number;
  collectionRate: number;
};

export type CollectionRateSummary = {
  rows: CollectionRateRow[];
  overallRate: number;
  totalBilled: number;
  totalPaid: number;
  totalDue: number;
};

export type DSOResult = {
  dso: number;
  accountsReceivable: number;
  totalSales: number;
  daysPeriod: number;
  averageDaysToCollect: number;
};

export type TopDebtorRow = {
  customerId: string;
  customerName: string;
  totalBilled: number;
  totalPaid: number;
  amountDue: number;
  oldestUnpaidDate: string;
};

export type DiscountAnalysisSummary = {
  totalGross: number;
  totalDiscount: number;
  totalNet: number;
  overallDiscountRate: number;
  invoicesWithDiscount: number;
  totalInvoices: number;
};

export type PriceVarianceRow = {
  materialId: string;
  materialName: string;
  avgSellingPrice: number;
  purchaseCost: number;
  varianceAmount: number;
  variancePercent: number;
  quantitySold: number;
  totalProfit: number;
};

export type DailyPerformance = {
  date: string;
  invoiceCount: number;
  totalSales: number;
  returnCount: number;
  totalReturns: number;
  netSales: number;
  totalPaymentsReceived: number;
};

export type PeriodSnapshot = {
  fromDate: string;
  toDate: string;
  invoiceCount: number;
  totalSales: number;
  totalPaid: number;
  averageInvoice: number;
};

export type PeriodComparisonResult = {
  period1: PeriodSnapshot;
  period2: PeriodSnapshot;
  growthSales: number;
  growthInvoiceCount: number;
  growthAvgInvoice: number;
};

export type RevenueVsExpensesRow = {
  accountCode: string;
  accountName: string;
  accountType: 'revenue' | 'expense';
  totalAmount: number;
};

export type RevenueVsExpensesSummary = {
  rows: RevenueVsExpensesRow[];
  totalRevenue: number;
  totalExpenses: number;
  netIncome: number;
};

export type DwellTimeRow = {
  materialId: string;
  materialName: string;
  firstMovementDate: string;
  lastMovementDate: string;
  avgDaysInStock: number;
  currentStockQty: number;
};

// ─── Internal Helpers ────────────────────────────────────────────────────────

function normDate(value?: string | null): string {
  if (!value) return '';
  return String(value).trim().slice(0, 10);
}

function toNum(value: unknown): number {
  const n = Number(value ?? 0);
  return Number.isFinite(n) ? n : 0;
}

function withinRange(dateStr: string, fromDate?: string, toDate?: string): boolean {
  const d = normDate(dateStr);
  const from = normDate(fromDate);
  const to = normDate(toDate);
  if (from && d && d < from) return false;
  if (to && d && d > to) return false;
  return true;
}

function daysBetween(from: string, to: string): number {
  if (!from || !to) return 0;
  const a = new Date(`${normDate(from)}T00:00:00.000Z`);
  const b = new Date(`${normDate(to)}T00:00:00.000Z`);
  if (Number.isNaN(a.getTime()) || Number.isNaN(b.getTime())) return 0;
  return Math.max(0, Math.floor((b.getTime() - a.getTime()) / 86_400_000));
}

function todayStr(): string {
  return new Date().toISOString().slice(0, 10);
}

function activeNonReturnInvoices(invoices: SalesInvoice[], filters: AdvancedFilters) {
  return invoices.filter((inv) => {
    if (String(inv.status || 'active') !== 'active') return false;
    if (String(inv.type || 'sale') === 'return') return false;
    if (!withinRange(inv.date, filters.fromDate, filters.toDate)) return false;
    if (filters.customerId && String(inv.customerId || '').trim() !== filters.customerId) return false;
    return true;
  });
}

function buildMaterialIndex(materials: MaterialFull[]) {
  return new Map(materials.map((m) => [String(m.id || '').trim(), m]));
}

const DAY_NAMES_AR = ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'];

// ─── Builder Functions ───────────────────────────────────────────────────────

/** تقرير الربحية حسب الفاتورة */
export function buildProfitByInvoice(
  invoices: SalesInvoice[],
  materials: MaterialFull[],
  filters: AdvancedFilters,
): ProfitByInvoiceRow[] {
  const byId = buildMaterialIndex(materials);
  return activeNonReturnInvoices(invoices, filters).map((inv) => {
    const salesValue = toNum(inv.grandTotal);
    let estimatedCost = 0;
    (inv.items || []).forEach((item) => {
      const mat = byId.get(String(item.materialId || '').trim());
      estimatedCost += toNum(item.quantity) * toNum(mat?.purchasePrice);
    });
    const estimatedProfit = salesValue - estimatedCost;
    const profitMargin = salesValue > 0 ? (estimatedProfit / salesValue) * 100 : 0;
    return {
      invoiceId: String(inv.id || '').trim(),
      invoiceNumber: String(inv.invoiceNumber || '').trim(),
      date: normDate(inv.date),
      customerId: String(inv.customerId || '').trim(),
      customerName: String(inv.customerName || '').trim() || 'غير معروف',
      salesValue,
      estimatedCost,
      estimatedProfit,
      profitMargin,
    };
  }).sort((a, b) => normDate(b.date).localeCompare(normDate(a.date)));
}

/** تقرير تكرار الشراء وحالة العملاء */
export function buildCustomerFrequency(
  invoices: SalesInvoice[],
  filters: AdvancedFilters,
): CustomerFrequencyRow[] {
  const rows = activeNonReturnInvoices(invoices, filters);
  const today = todayStr();
  const map = new Map<string, CustomerFrequencyRow & { _dates: string[] }>();

  rows.forEach((inv) => {
    const key = String(inv.customerId || '').trim() || String(inv.customerName || '').trim() || 'unknown';
    const current = map.get(key) ?? {
      customerId: String(inv.customerId || '').trim() || key,
      customerName: String(inv.customerName || '').trim() || 'غير معروف',
      invoiceCount: 0,
      totalSales: 0,
      firstInvoiceDate: '',
      lastInvoiceDate: '',
      daysSinceLastPurchase: 0,
      avgDaysBetweenPurchases: null,
      _dates: [],
    };
    const d = normDate(inv.date);
    current.invoiceCount += 1;
    current.totalSales += toNum(inv.grandTotal);
    current._dates.push(d);
    if (!current.firstInvoiceDate || d < current.firstInvoiceDate) current.firstInvoiceDate = d;
    if (!current.lastInvoiceDate || d > current.lastInvoiceDate) current.lastInvoiceDate = d;
    map.set(key, current);
  });

  return Array.from(map.values()).map(({ _dates, ...row }) => {
    const sorted = [..._dates].sort();
    let avgDays: number | null = null;
    if (sorted.length >= 2) {
      let totalGap = 0;
      for (let i = 1; i < sorted.length; i++) {
        totalGap += daysBetween(sorted[i - 1], sorted[i]);
      }
      avgDays = Math.round(totalGap / (sorted.length - 1));
    }
    return {
      ...row,
      daysSinceLastPurchase: daysBetween(row.lastInvoiceDate, today),
      avgDaysBetweenPurchases: avgDays,
    };
  }).sort((a, b) => b.invoiceCount - a.invoiceCount);
}

/** تقرير العملاء غير النشطين */
export function buildInactiveCustomers(
  rows: CustomerFrequencyRow[],
  thresholdDays: number,
): CustomerFrequencyRow[] {
  return rows
    .filter((row) => row.daysSinceLastPurchase >= thresholdDays)
    .sort((a, b) => b.daysSinceLastPurchase - a.daysSinceLastPurchase);
}

/** تقرير أفضل وقت للبيع (حسب يوم الأسبوع) */
export function buildBestSellingTime(
  invoices: SalesInvoice[],
  filters: AdvancedFilters,
): BestSellingTimeRow[] {
  const rows = activeNonReturnInvoices(invoices, filters);
  const byDay = new Map<number, BestSellingTimeRow>();

  for (let dow = 0; dow < 7; dow++) {
    byDay.set(dow, {
      dayOfWeek: dow,
      dayNameAr: DAY_NAMES_AR[dow],
      invoiceCount: 0,
      totalSales: 0,
      averageSale: 0,
    });
  }

  rows.forEach((inv) => {
    const d = normDate(inv.date);
    if (!d) return;
    const dow = new Date(`${d}T12:00:00.000Z`).getDay();
    const current = byDay.get(dow)!;
    current.invoiceCount += 1;
    current.totalSales += toNum(inv.grandTotal);
  });

  return Array.from(byDay.values()).map((row) => ({
    ...row,
    averageSale: row.invoiceCount > 0 ? row.totalSales / row.invoiceCount : 0,
  }));
}

/** تقرير أداء المستودعات / الفروع */
export function buildBranchPerformance(
  invoices: SalesInvoice[],
  materials: MaterialFull[],
  filters: AdvancedFilters,
): BranchPerformanceRow[] {
  const rows = activeNonReturnInvoices(invoices, filters);
  const byId = buildMaterialIndex(materials);
  const invoiceSet = new Set<string>();
  const map = new Map<string, BranchPerformanceRow & { _invoices: Set<string> }>();

  rows.forEach((inv) => {
    const invKey = String(inv.id || '').trim();
    (inv.items || []).forEach((item) => {
      const warehouseId = String(item.warehouseId || 'غير محدد').trim();
      const current = map.get(warehouseId) ?? {
        warehouseId,
        invoiceCount: 0,
        lineCount: 0,
        totalQuantity: 0,
        totalSales: 0,
        estimatedCost: 0,
        estimatedProfit: 0,
        profitMargin: 0,
        _invoices: new Set<string>(),
      };
      const qty = toNum(item.quantity);
      const lineTotal = toNum(item.total || qty * toNum(item.unitPrice));
      const mat = byId.get(String(item.materialId || '').trim());
      const lineCost = qty * toNum(mat?.purchasePrice);

      current._invoices.add(invKey);
      current.lineCount += 1;
      current.totalQuantity += qty;
      current.totalSales += lineTotal;
      current.estimatedCost += lineCost;
      map.set(warehouseId, current);
    });
    invoiceSet.add(invKey);
  });

  return Array.from(map.values()).map(({ _invoices, ...row }) => {
    const profit = row.totalSales - row.estimatedCost;
    return {
      ...row,
      invoiceCount: _invoices.size,
      estimatedProfit: profit,
      profitMargin: row.totalSales > 0 ? (profit / row.totalSales) * 100 : 0,
    };
  }).sort((a, b) => b.totalSales - a.totalSales);
}

/** تقرير أداء الفئات */
export function buildCategoryPerformance(
  invoices: SalesInvoice[],
  materials: MaterialFull[],
  groups: GroupLite[],
  filters: AdvancedFilters,
): CategoryPerformanceRow[] {
  const rows = activeNonReturnInvoices(invoices, filters);
  const byId = buildMaterialIndex(materials);
  const groupMap = new Map(groups.map((g) => [String(g.id || '').trim(), String(g.name || '').trim()]));
  const map = new Map<string, Omit<CategoryPerformanceRow, 'profitMargin'>>();

  rows.forEach((inv) => {
    (inv.items || []).forEach((item) => {
      const mat = byId.get(String(item.materialId || '').trim());
      const groupId = String(mat?.groupId || 'ungrouped').trim();
      const groupName = groupMap.get(groupId) || (groupId === 'ungrouped' ? 'غير مصنّف' : groupId);
      const current = map.get(groupId) ?? {
        groupId,
        groupName,
        lineCount: 0,
        totalQuantity: 0,
        totalSales: 0,
        estimatedCost: 0,
        estimatedProfit: 0,
      };
      const qty = toNum(item.quantity);
      const lineTotal = toNum(item.total || qty * toNum(item.unitPrice));
      const lineCost = qty * toNum(mat?.purchasePrice);
      current.lineCount += 1;
      current.totalQuantity += qty;
      current.totalSales += lineTotal;
      current.estimatedCost += lineCost;
      current.estimatedProfit = current.totalSales - current.estimatedCost;
      map.set(groupId, current);
    });
  });

  return Array.from(map.values()).map((row) => ({
    ...row,
    profitMargin: row.totalSales > 0 ? (row.estimatedProfit / row.totalSales) * 100 : 0,
  })).sort((a, b) => b.totalSales - a.totalSales);
}

/** تقرير نسبة التحصيل */
export function buildCollectionRate(
  invoices: SalesInvoice[],
  filters: AdvancedFilters,
): CollectionRateSummary {
  const rows = activeNonReturnInvoices(invoices, filters);
  const map = new Map<string, CollectionRateRow>();

  rows.forEach((inv) => {
    const key = String(inv.customerId || '').trim() || String(inv.customerName || '').trim() || 'unknown';
    const current = map.get(key) ?? {
      customerId: String(inv.customerId || '').trim() || key,
      customerName: String(inv.customerName || '').trim() || 'غير معروف',
      totalBilled: 0,
      totalPaid: 0,
      totalDue: 0,
      collectionRate: 0,
    };
    current.totalBilled += toNum(inv.grandTotal);
    current.totalPaid += toNum(inv.amountPaid);
    map.set(key, current);
  });

  const result = Array.from(map.values()).map((row) => ({
    ...row,
    totalDue: row.totalBilled - row.totalPaid,
    collectionRate: row.totalBilled > 0 ? (row.totalPaid / row.totalBilled) * 100 : 0,
  })).sort((a, b) => b.totalBilled - a.totalBilled);

  const totalBilled = result.reduce((s, r) => s + r.totalBilled, 0);
  const totalPaid = result.reduce((s, r) => s + r.totalPaid, 0);

  return {
    rows: result,
    overallRate: totalBilled > 0 ? (totalPaid / totalBilled) * 100 : 0,
    totalBilled,
    totalPaid,
    totalDue: totalBilled - totalPaid,
  };
}

/** تقرير متوسط فترة التحصيل (DSO) */
export function buildDSO(
  invoices: SalesInvoice[],
  payments: CustomerPayment[],
  filters: AdvancedFilters,
): DSOResult {
  const salesRows = activeNonReturnInvoices(invoices, filters);
  const totalSales = salesRows.reduce((s, inv) => s + toNum(inv.grandTotal), 0);
  const accountsReceivable = salesRows.reduce((s, inv) => s + toNum(inv.amountDue), 0);

  // Days in period
  const from = normDate(filters.fromDate);
  const to = normDate(filters.toDate) || todayStr();
  const daysPeriod = from ? daysBetween(from, to) || 30 : 30;
  const dso = totalSales > 0 ? (accountsReceivable / totalSales) * daysPeriod : 0;

  // Average actual days to collect using payment allocations
  const invoiceDateMap = new Map(salesRows.map((inv) => [String(inv.id || '').trim(), normDate(inv.date)]));
  let totalDaysToCollect = 0;
  let paidCount = 0;

  (payments || []).forEach((payment) => {
    if (String(payment.status || 'active') !== 'active') return;
    if (!withinRange(payment.date, filters.fromDate, filters.toDate)) return;
    const paymentDate = normDate(payment.date);
    (payment.allocations || []).forEach((alloc) => {
      const invoiceDate = invoiceDateMap.get(String(alloc.invoiceId || '').trim());
      if (!invoiceDate) return;
      const d = daysBetween(invoiceDate, paymentDate);
      totalDaysToCollect += d;
      paidCount += 1;
    });
  });

  return {
    dso: Math.round(dso * 10) / 10,
    accountsReceivable,
    totalSales,
    daysPeriod,
    averageDaysToCollect: paidCount > 0 ? Math.round(totalDaysToCollect / paidCount) : 0,
  };
}

/** تقرير أعلى العملاء مديونية */
export function buildTopDebtors(
  invoices: SalesInvoice[],
  filters: AdvancedFilters,
  limit = 20,
): TopDebtorRow[] {
  const rows = activeNonReturnInvoices(invoices, filters).filter((inv) => toNum(inv.amountDue) > 0.001);
  const map = new Map<string, TopDebtorRow>();

  rows.forEach((inv) => {
    const key = String(inv.customerId || '').trim() || String(inv.customerName || '').trim() || 'unknown';
    const current = map.get(key) ?? {
      customerId: String(inv.customerId || '').trim() || key,
      customerName: String(inv.customerName || '').trim() || 'غير معروف',
      totalBilled: 0,
      totalPaid: 0,
      amountDue: 0,
      oldestUnpaidDate: '',
    };
    current.totalBilled += toNum(inv.grandTotal);
    current.totalPaid += toNum(inv.amountPaid);
    current.amountDue += toNum(inv.amountDue);
    const d = normDate(inv.date);
    if (!current.oldestUnpaidDate || d < current.oldestUnpaidDate) {
      current.oldestUnpaidDate = d;
    }
    map.set(key, current);
  });

  return Array.from(map.values())
    .filter((r) => r.amountDue > 0.001)
    .sort((a, b) => b.amountDue - a.amountDue)
    .slice(0, limit);
}

/** تقرير تحليل الخصومات */
export function buildDiscountAnalysis(
  invoices: SalesInvoice[],
  filters: AdvancedFilters,
): DiscountAnalysisSummary {
  const rows = activeNonReturnInvoices(invoices, filters);
  let totalGross = 0;
  let totalDiscount = 0;
  let invoicesWithDiscount = 0;

  rows.forEach((inv) => {
    const subTotal = toNum(inv.subTotal);
    const grandTotal = toNum(inv.grandTotal);
    const discountAmt = toNum(inv.discountAmount) + toNum(inv.campaignDiscountAmount);
    const lineDiscounts = (inv.items || []).reduce((s, item) => {
      const qty = toNum(item.quantity);
      const unitPrice = toNum(item.unitPrice);
      const lineDiscount = toNum(item.discount); // discount % per item
      return s + qty * unitPrice * (lineDiscount / 100);
    }, 0);

    const totalDiscountForInv = discountAmt > 0 ? discountAmt : lineDiscounts;
    const gross = subTotal > 0 ? subTotal : grandTotal + totalDiscountForInv;
    totalGross += gross;
    totalDiscount += totalDiscountForInv;
    if (totalDiscountForInv > 0.001) invoicesWithDiscount += 1;
  });

  const totalNet = totalGross - totalDiscount;

  return {
    totalGross,
    totalDiscount,
    totalNet,
    overallDiscountRate: totalGross > 0 ? (totalDiscount / totalGross) * 100 : 0,
    invoicesWithDiscount,
    totalInvoices: rows.length,
  };
}

/** تقرير الفرق بين سعر البيع والتكلفة */
export function buildPriceVariance(
  invoices: SalesInvoice[],
  materials: MaterialFull[],
  filters: AdvancedFilters,
): PriceVarianceRow[] {
  const rows = activeNonReturnInvoices(invoices, filters);
  const byId = buildMaterialIndex(materials);
  const map = new Map<string, { name: string; totalRevenue: number; totalCost: number; totalQty: number; purchaseCost: number }>();

  rows.forEach((inv) => {
    (inv.items || []).forEach((item) => {
      const matId = String(item.materialId || '').trim();
      const mat = byId.get(matId);
      const qty = toNum(item.quantity);
      const lineTotal = toNum(item.total || qty * toNum(item.unitPrice));
      const unitCost = toNum(mat?.purchasePrice);
      const lineCost = qty * unitCost;
      const current = map.get(matId) ?? {
        name: String(mat?.name || item.name || matId || 'غير معروف').trim(),
        totalRevenue: 0,
        totalCost: 0,
        totalQty: 0,
        purchaseCost: unitCost,
      };
      current.totalRevenue += lineTotal;
      current.totalCost += lineCost;
      current.totalQty += qty;
      map.set(matId, current);
    });
  });

  return Array.from(map.entries()).map(([materialId, data]) => {
    const avgSellingPrice = data.totalQty > 0 ? data.totalRevenue / data.totalQty : 0;
    const varianceAmount = avgSellingPrice - data.purchaseCost;
    const variancePercent = data.purchaseCost > 0 ? (varianceAmount / data.purchaseCost) * 100 : 0;
    return {
      materialId,
      materialName: data.name,
      avgSellingPrice,
      purchaseCost: data.purchaseCost,
      varianceAmount,
      variancePercent,
      quantitySold: data.totalQty,
      totalProfit: data.totalRevenue - data.totalCost,
    };
  }).filter((r) => r.quantitySold > 0).sort((a, b) => b.totalProfit - a.totalProfit);
}

/** تقرير الأداء اليومي */
export function buildDailyPerformance(
  invoices: SalesInvoice[],
  payments: CustomerPayment[],
  targetDate?: string,
): DailyPerformance {
  const date = normDate(targetDate) || todayStr();
  const activeInvs = invoices.filter((inv) => String(inv.status || 'active') === 'active');
  const dayInvoices = activeInvs.filter((inv) => normDate(inv.date) === date);
  const sales = dayInvoices.filter((inv) => String(inv.type || 'sale') !== 'return');
  const returns = dayInvoices.filter((inv) => String(inv.type || 'sale') === 'return');
  const totalSales = sales.reduce((s, inv) => s + toNum(inv.grandTotal), 0);
  const totalReturns = returns.reduce((s, inv) => s + toNum(inv.grandTotal), 0);

  const dayPayments = (payments || []).filter(
    (p) => normDate(p.date) === date && String(p.status || 'active') === 'active',
  );
  const totalPaymentsReceived = dayPayments.reduce((s, p) => s + toNum(p.amount), 0);

  return {
    date,
    invoiceCount: sales.length,
    totalSales,
    returnCount: returns.length,
    totalReturns,
    netSales: totalSales - totalReturns,
    totalPaymentsReceived,
  };
}

/** تقرير مقارنة الفترات */
export function buildPeriodComparison(
  invoices: SalesInvoice[],
  period1From: string,
  period1To: string,
  period2From: string,
  period2To: string,
): PeriodComparisonResult {
  function snapshot(from: string, to: string): PeriodSnapshot {
    const rows = invoices.filter((inv) => {
      if (String(inv.status || 'active') !== 'active') return false;
      if (String(inv.type || 'sale') === 'return') return false;
      return withinRange(inv.date, from, to);
    });
    const totalSales = rows.reduce((s, inv) => s + toNum(inv.grandTotal), 0);
    const totalPaid = rows.reduce((s, inv) => s + toNum(inv.amountPaid), 0);
    return {
      fromDate: normDate(from),
      toDate: normDate(to),
      invoiceCount: rows.length,
      totalSales,
      totalPaid,
      averageInvoice: rows.length > 0 ? totalSales / rows.length : 0,
    };
  }

  const p1 = snapshot(period1From, period1To);
  const p2 = snapshot(period2From, period2To);

  const growthSales = p1.totalSales > 0 ? ((p2.totalSales - p1.totalSales) / p1.totalSales) * 100 : 0;
  const growthInvoiceCount = p1.invoiceCount > 0 ? ((p2.invoiceCount - p1.invoiceCount) / p1.invoiceCount) * 100 : 0;
  const growthAvgInvoice = p1.averageInvoice > 0 ? ((p2.averageInvoice - p1.averageInvoice) / p1.averageInvoice) * 100 : 0;

  return { period1: p1, period2: p2, growthSales, growthInvoiceCount, growthAvgInvoice };
}

/** تقرير الإيرادات مقابل المصاريف (من القيود المحاسبية) */
export function buildRevenueVsExpenses(
  journalEntries: JournalEntry[],
  filters: AdvancedFilters,
): RevenueVsExpensesSummary {
  const map = new Map<string, RevenueVsExpensesRow>();

  (journalEntries || []).forEach((entry) => {
    if (!withinRange(entry.date, filters.fromDate, filters.toDate)) return;
    (entry.lines || []).forEach((line) => {
      const code = String(line.accountCode || '').trim();
      if (!code) return;
      const isRevenue = code.startsWith('4');
      const isExpense = code.startsWith('5');
      if (!isRevenue && !isExpense) return;

      const accountType: 'revenue' | 'expense' = isRevenue ? 'revenue' : 'expense';
      const amount = isRevenue
        ? toNum(line.credit) - toNum(line.debit)
        : toNum(line.debit) - toNum(line.credit);

      const current = map.get(code) ?? {
        accountCode: code,
        accountName: String(line.accountName || code).trim(),
        accountType,
        totalAmount: 0,
      };
      current.totalAmount += amount;
      map.set(code, current);
    });
  });

  const rows = Array.from(map.values())
    .filter((r) => Math.abs(r.totalAmount) > 0.001)
    .sort((a, b) => {
      if (a.accountType !== b.accountType) return a.accountType === 'revenue' ? -1 : 1;
      return b.totalAmount - a.totalAmount;
    });

  const totalRevenue = rows.filter((r) => r.accountType === 'revenue').reduce((s, r) => s + r.totalAmount, 0);
  const totalExpenses = rows.filter((r) => r.accountType === 'expense').reduce((s, r) => s + r.totalAmount, 0);

  return {
    rows,
    totalRevenue,
    totalExpenses,
    netIncome: totalRevenue - totalExpenses,
  };
}

/** تقرير مدة بقاء الصنف في المخزون */
export function buildDwellTime(
  movements: InventoryMovement[],
  materials: MaterialFull[],
  filters: AdvancedFilters,
): DwellTimeRow[] {
  const byId = buildMaterialIndex(materials);
  const grouped = new Map<string, { dates: string[]; in: number; out: number }>();

  (movements || []).forEach((mov) => {
    if (!withinRange(mov.date, filters.fromDate, filters.toDate)) return;
    const matId = String(mov.materialId || '').trim();
    if (!matId) return;
    const current = grouped.get(matId) ?? { dates: [], in: 0, out: 0 };
    const d = normDate(mov.date);
    if (d) current.dates.push(d);
    current.in += toNum(mov.quantityIn);
    current.out += toNum(mov.quantityOut);
    grouped.set(matId, current);
  });

  const today = todayStr();
  return Array.from(grouped.entries()).map(([matId, data]) => {
    const mat = byId.get(matId);
    const sorted = [...data.dates].sort();
    const first = sorted[0] || '';
    const last = sorted[sorted.length - 1] || '';
    const spanDays = first && last ? daysBetween(first, today) : 0;
    return {
      materialId: matId,
      materialName: String(mat?.name || matId).trim(),
      firstMovementDate: first,
      lastMovementDate: last,
      avgDaysInStock: spanDays,
      currentStockQty: data.in - data.out,
    };
  }).filter((r) => r.currentStockQty > 0).sort((a, b) => b.avgDaysInStock - a.avgDaysInStock);
}
