<?php

namespace App\Services;

/**
 * Invoice Calculator Service
 * 
 * Converts Excel business logic to PHP:
 * K42 = SUM(G17:I41)     -> calculateDisbursements()
 * D44 = B44 * A44        -> calculateVat()
 * K44 = B44              -> vatBase = subtotal
 * K45 = D44              -> vatAmount
 * K47 = SUM(K42:L46)     -> calculateTotal()
 * K49 = K47 - K48        -> calculateNetPayable()
 */
class InvoiceCalculatorService
{
    /**
     * Calculate all invoice totals from lines
     * 
     * @param array $lines Array of invoice lines
     * @param float $vatRate VAT rate (default 19%)
     * @param float $discountPercent Discount percentage
     * @param float $advanceAmount Advance payment amount
     * @param float $stampDuty Stamp duty amount
     * @return array Calculated totals
     */
    public function calculate(array $lines, float $vatRate = 0.19, float $discountPercent = 0, float $advanceAmount = 0, float $stampDuty = 1): array
    {
        // Step 1: Calculate disbursements (Débours) = SUM of all line amounts
        // Excel: K42 = SUM(G17:I41)
        $disbursements = $this->calculateDisbursements($lines);

        // Step 2: Calculate subtotal (all taxable lines)
        $subtotal = $this->calculateSubtotal($lines);

        // Step 3: Apply discount
        // Excel: discount is applied before VAT
        $discountAmount = $subtotal * ($discountPercent / 100);
        $discountedSubtotal = $subtotal - $discountAmount;

        // Step 4: Calculate VAT base and amount
        // Excel: D44 = B44 * A44 (Base * Taux)
        $vatBase = $discountedSubtotal;
        $vatAmount = $this->calculateVat($vatBase, $vatRate);

        // Step 5: Calculate total
        // Excel: K47 = SUM(K42:L46) = Débours + Taxables + TVA + Timbre
        $totalTTC = $this->calculateTotal($disbursements, $vatBase, $vatAmount, $stampDuty);

        // Step 6: Calculate net payable
        // Excel: K49 = K47 - K48 (Total - Avance)
        $netPayable = $this->calculateNetPayable($totalTTC, $advanceAmount);

        return [
            'disbursements' => round($disbursements, 4),
            'subtotal' => round($subtotal, 4),
            'discount_amount' => round($discountAmount, 4),
            'discount_percent' => $discountPercent,
            'vat_base' => round($vatBase, 4),
            'vat_rate' => $vatRate,
            'vat_amount' => round($vatAmount, 4),
            'stamp_duty' => round($stampDuty, 4),
            'total_ht' => round($discountedSubtotal, 4),
            'total_ttc' => round($totalTTC, 4),
            'advance_amount' => round($advanceAmount, 4),
            'net_payable' => round($netPayable, 4),
        ];
    }

    /**
     * Calculate disbursements (Débours)
     * Excel equivalent: =SUM(G17:I41)
     * Sums all non-taxable line amounts
     */
    public function calculateDisbursements(array $lines): float
    {
        $total = 0;
        foreach ($lines as $line) {
            if (empty($line['is_taxable'])) {
                $total += (float) ($line['amount'] ?? 0);
            }
        }
        return $total;
    }

    /**
     * Calculate subtotal (taxable base)
     * Sums all taxable line amounts
     */
    public function calculateSubtotal(array $lines): float
    {
        $total = 0;
        foreach ($lines as $line) {
            if (!empty($line['is_taxable'])) {
                $total += (float) ($line['amount'] ?? 0);
            }
        }
        return $total;
    }

    /**
     * Calculate VAT amount
     * Excel equivalent: =B44*A44 (Base * Rate)
     */
    public function calculateVat(float $base, float $rate): float
    {
        return $base * $rate;
    }

    /**
     * Calculate total TTC
     * Excel equivalent: =SUM(K42:L46)
     * Total = Débours + VAT Base + VAT Amount + Stamp Duty
     */
    public function calculateTotal(float $disbursements, float $vatBase, float $vatAmount, float $stampDuty): float
    {
        return $disbursements + $vatBase + $vatAmount + $stampDuty;
    }

    /**
     * Calculate net payable
     * Excel equivalent: =K47-K48 (Total - Advance)
     */
    public function calculateNetPayable(float $total, float $advance): float
    {
        return max(0, $total - $advance);
    }

    /**
     * Calculate line amount from quantity and unit price
     * Excel equivalent: implicit in each row
     */
    public function calculateLineAmount(float $quantity, float $unitPrice): float
    {
        return $quantity * $unitPrice;
    }

    /**
     * Recalculate all lines and return updated lines with amounts
     */
    public function recalculateLines(array $lines): array
    {
        foreach ($lines as &$line) {
            $qty = (float) ($line['quantity'] ?? 1);
            $price = (float) ($line['unit_price'] ?? 0);
            $line['amount'] = $this->calculateLineAmount($qty, $price);
        }
        return $lines;
    }

    /**
     * Validate invoice totals (checksum verification)
     */
    public function validateTotals(array $totals): bool
    {
        $expectedTotal = $totals['disbursements'] + $totals['vat_base'] + $totals['vat_amount'] + $totals['stamp_duty'];
        $expectedNet = $expectedTotal - $totals['advance_amount'];

        return 
            abs($expectedTotal - $totals['total_ttc']) < 0.01 &&
            abs($expectedNet - $totals['net_payable']) < 0.01;
    }
}
