// composables/usePaymentCalculator.js
import { ref, computed } from 'vue';

export function usePaymentCalculator() {
  // Inputs cơ bản
  const originPrice = ref(0);
  const discounts = ref([]); // [{ id, name, code, type: 1 (percent) | 2 (fixed), value: number }]
  const paymentPlan = ref([]); // [{cycle, value, type: 1 (percent) | other (fixed), days, ...}]
  const contractAllocationPercentage = ref(100);
  const startDate = ref(new Date());

  // Thanh toán sớm
  const earlyPaymentCycles = ref(0);
  const earlyDiscountRate = ref(0.0191780821918);

  // Số tiền đã thanh toán thực tế
  const paidAmount = ref(0);

  // Tiền gốc
  const originalPrice = computed(() => originPrice.value);

  // Chi tiết chiết khấu
  const detailedDiscounts = computed(() => {
    const details = [];
    let currentBalance = originPrice.value || 0;

    discounts.value.forEach(discountData => {
      const d = discountData;
      let amount = 0;
      if (d.type === 1) { // percent
        amount = (currentBalance * Number(d.value)) / 100;
      } else { // fixed
        amount = Number(d.value);
      }
      if (currentBalance - amount < 0) {
        amount = currentBalance;
      }
      currentBalance -= amount;

      details.push({
        id: d.id,
        name: d.name,
        code: d.code,
        customValue: d.value,
        customType: d.type,
        amount: amount,
        remaining: currentBalance
      });
    });
    return details;
  });

  // Tổng tiền giảm giá từ discounts
  const totalDiscount = computed(() => {
    return detailedDiscounts.value.reduce((sum, d) => sum + d.amount, 0);
  });

  // Giá sau chiết khấu
  const salePrice = computed(() => {
    const lastDiscount = detailedDiscounts.value[detailedDiscounts.value.length - 1];
    return lastDiscount ? lastDiscount.remaining : originPrice.value;
  });

  const allocatedAmount = computed(() => {
    const amount = salePrice.value * (contractAllocationPercentage.value / 100);
    return Math.round(amount / 1000) * 1000;
  });

  const finalTotal = computed(() => allocatedAmount.value);

  // Lịch thanh toán gốc (hỗ trợ cả percent và fixed cho paymentPlan.type)
  const originalPaymentSchedule = computed(() => {
    const schedule = [];
    let remaining = allocatedAmount.value;

    const sortedPlan = [...paymentPlan.value].sort((a, b) => a.cycle - b.cycle);

    let lastToDateForPeriodCalc = new Date(startDate.value); // Used to calculate the duration of each installment period.

    sortedPlan.forEach(plan => {
      let amount = 0;

      // Xử lý linh hoạt theo type của Payment_Plan
      if (plan.type === 1) {
        // percent
        amount = allocatedAmount.value * (plan.value / 100);
      } else {
        // fixed (type 2 hoặc bất kỳ giá trị khác)
        amount = plan.value || 0;
      }

      const adjustedAmount = Math.min(amount, remaining);
      remaining -= adjustedAmount;

      const fromDate = new Date(startDate.value); // Per user request, all installments start from the same date.
      const toDate = new Date(startDate.value);
      toDate.setDate(toDate.getDate() + (plan.days || 0));

      // The duration of the installment period is the difference between this installment's due date and the previous one.
      const daysInPeriod = Math.round((toDate.getTime() - lastToDateForPeriodCalc.getTime()) / (1000 * 60 * 60 * 24));

      schedule.push({
        cycle: plan.cycle,
        from_date: fromDate,
        to_date: toDate,
        amount: adjustedAmount,
        paid_amount: 0,
        remain_amount: adjustedAmount,
        days: daysInPeriod > 0 ? daysInPeriod : 0, // Use calculated period duration; it cannot be negative.
        status: 1,
        type: plan.type,
        value: plan.value,
        payment_note: `Thanh toán theo kế hoạch đợt số ${plan.cycle}`
      });

      lastToDateForPeriodCalc = new Date(toDate); // Update the last due date for the next period's duration calculation.
    });

    // Cộng phần dư (nếu có) vào đợt cuối
    if (remaining > 0 && schedule.length > 0) {
      const last = schedule[schedule.length - 1];
      last.amount += remaining;
      last.remain_amount += remaining;
    }

    return schedule;
  });

  // Chiết khấu thanh toán sớm
  const earlyDiscounts = computed(() => {
    if (earlyPaymentCycles.value <= 0) return [];

    const schedule = originalPaymentSchedule.value;
    const numEarly = Math.min(earlyPaymentCycles.value, schedule.length);
    const actualPaymentDate = new Date(startDate.value);
    const actualPaymentDateOnly = new Date(actualPaymentDate.getFullYear(), actualPaymentDate.getMonth(), actualPaymentDate.getDate());

    return schedule.slice(0, numEarly).map(item => {
      const originalDate = new Date(item.to_date);
      const originalDateOnly = new Date(originalDate.getFullYear(), originalDate.getMonth(), originalDate.getDate());
      const earlyDays = Math.round((originalDateOnly.getTime() - actualPaymentDateOnly.getTime()) / (1000 * 60 * 60 * 24));

      if (earlyDays <= 0) {
        return 0;
      }
      return item.amount * earlyDays * (earlyDiscountRate.value / 100);
    });
  });

  const totalEarlyDiscount = computed(() => {
    const rawTotal = earlyDiscounts.value.reduce((sum, disc) => sum + disc, 0);
    return parseInt(rawTotal);
  });

  // Chi tiết chiết khấu thanh toán sớm
  const earlyDiscountDetails = computed(() => {
    if (earlyPaymentCycles.value <= 0) return [];

    const schedule = originalPaymentSchedule.value;
    const numEarly = Math.min(earlyPaymentCycles.value, schedule.length);
    const actualPaymentDate = new Date(startDate.value);
    const actualPaymentDateOnly = new Date(actualPaymentDate.getFullYear(), actualPaymentDate.getMonth(), actualPaymentDate.getDate());

    return schedule.slice(0, numEarly).map((item, index) => {
      const originalDate = new Date(item.to_date);
      const originalDateOnly = new Date(originalDate.getFullYear(), originalDate.getMonth(), originalDate.getDate());
      const earlyDays = Math.round((originalDateOnly.getTime() - actualPaymentDateOnly.getTime()) / (1000 * 60 * 60 * 24));

      return {
        cycle: item.cycle,
        original_payment_date: originalDate,
        actual_payment_date: actualPaymentDate,
        early_days: earlyDays > 0 ? earlyDays : 0,
        original_amount: item.amount,
        discount_rate: earlyDiscountRate.value,
        discount_amount: earlyDiscounts.value[index] || 0,
      };
    });
  });

  // Lịch sau thanh toán sớm (gộp đợt)
  const scheduleAfterEarly = computed(() => {
    const base = originalPaymentSchedule.value;
    const numEarly = Math.min(earlyPaymentCycles.value, base.length);

    if (numEarly <= 0) return base;

    const earlyItems = base.slice(0, numEarly);
    const totalEarlyAmount = earlyItems.reduce((sum, i) => sum + i.amount, 0);
    const mergedAmount = totalEarlyAmount - totalEarlyDiscount.value;

    const originalCycles = earlyItems.map(i => i.cycle);

    const mergedItem = {
      cycle: 1,
      from_date: earlyItems[0].from_date,
      to_date: earlyItems[0].from_date, // Due date is the start date for the merged installment
      amount: Math.max(0, mergedAmount),
      paid_amount: 0,
      remain_amount: Math.max(0, mergedAmount),
      payment_note: `Thanh toán gộp đợt ${originalCycles.join(', ')} (đã trừ số tiền chiết khấu thanh toán sớm là ${totalEarlyDiscount.value})`,
      days: 0,
      status: 1,
      is_merged: true,
      original_cycles: originalCycles
    };

    const remainingItems = base.slice(numEarly).map((item, idx) => ({
      ...item,
      cycle: idx + 2,
    }));

    return [mergedItem, ...remainingItems];
  });

  // Lịch thanh toán cuối cùng
  const finalPaymentSchedule = computed(() => {
    const schedule = scheduleAfterEarly.value.map(item => ({ ...item }));
    let remainingPaid = paidAmount.value || 0;

    for (let i = 0; i < schedule.length && remainingPaid > 0; i++) {
      const item = schedule[i];
      const canPay = Math.min(remainingPaid, item.remain_amount);

      item.paid_amount += canPay;
      item.remain_amount -= canPay;
      remainingPaid -= canPay;

      if (item.remain_amount <= 0) {
        item.status = 2;
        item.remain_amount = 0;
      }
    }

    return schedule;
  });

  const totalRemaining = computed(() =>
    finalPaymentSchedule.value.reduce((sum, item) => sum + item.remain_amount, 0)
  );

  return {
    originPrice,
    discounts,
    paymentPlan,
    contractAllocationPercentage,
    startDate,
    earlyPaymentCycles,
    earlyDiscountRate,
    paidAmount,

    originalPrice,
    detailedDiscounts,
    totalDiscount,
    salePrice,
    allocatedAmount,
    finalTotal,
    finalPaymentSchedule,
    originalPaymentSchedule,
    earlyDiscountDetails,
    totalEarlyDiscount,
    totalRemaining,
  };
}