<?php
/**
 * KDV Hesaplama Motoru - Production Grade
 * 
 * - Basis point KDV oranları (ZERO float)
 * - Pure integer arithmetic
 * - Satır bazlı hesaplama
 * - Telafi algoritması (e-fatura uyumlu)
 * - Dinamik KDV oranı desteği
 * 
 * @package Odjoo
 * @category Finance
 * @author Production Team
 * @version 2.0.0
 */
class TaxEngine
{
    /**
     * Basis point'ten decimal'e çevir (sadece gösterim için)
     * 
     * @param int $basisPoints Basis points (örn: 2000 = %20)
     * @return float Decimal (örn: 0.20)
     */
    private static function basisToDecimal(int $basisPoints): float
    {
        return $basisPoints / 10000.0;
    }
    
    /**
     * Yüzdeden basis point'e çevir
     * 
     * @param float $percent Yüzde (örn: 20.0 = %20)
     * @return int Basis points (örn: 2000)
     */
    public static function percentToBasis(float $percent): int
    {
        return (int) round($percent * 100);
    }
    
    /**
     * Basis point'ten yüzdeye çevir
     * 
     * @param int $basisPoints Basis points
     * @return float Yüzde
     */
    public static function basisToPercent(int $basisPoints): float
    {
        return $basisPoints / 100.0;
    }
    
    /**
     * KDV dahil fiyattan net hesapla (PURE INTEGER)
     * 
     * Formül: net = gross * 10000 / (10000 + vatBasis)
     * 
     * FLOAT KULLANILMAZ - Sadece integer division
     * 
     * @param int $grossKurus Brüt fiyat (kuruş)
     * @param int $vatBasis KDV oranı (basis points)
     * @return int Net fiyat (kuruş)
     * 
     * @example
     * // 120 TL (KDV dahil), %20 KDV
     * $net = TaxEngine::calculateNetFromGross(12000, 2000);
     * // Returns: 10000 (100 TL)
     */
    public static function calculateNetFromGross(int $grossKurus, int $vatBasis): int
    {
        if ($grossKurus <= 0) {
            return 0;
        }
        
        if ($vatBasis < 0 || $vatBasis > 10000) {
            throw new InvalidArgumentException("Geçersiz KDV oranı: {$vatBasis} basis points");
        }
        
        // Integer division - NO FLOAT
        // net = gross * 10000 / (10000 + vatBasis)
        return intdiv($grossKurus * 10000, 10000 + $vatBasis);
    }
    
    /**
     * Net fiyattan KDV hesapla (PURE INTEGER)
     * 
     * Formül: vat = net * vatBasis / 10000
     * 
     * FLOAT KULLANILMAZ - Sadece integer division
     * 
     * @param int $netKurus Net fiyat (kuruş)
     * @param int $vatBasis KDV oranı (basis points)
     * @param string $roundingStrategy Rounding strategy
     * @return int KDV tutarı (kuruş)
     * 
     * @example
     * // 100 TL, %20 KDV
     * $vat = TaxEngine::calculateVatFromNet(10000, 2000);
     * // Returns: 2000 (20 TL)
     */
    public static function calculateVatFromNet(int $netKurus, int $vatBasis, string $roundingStrategy = 'HALF_UP'): int
    {
        if ($netKurus <= 0) {
            return 0;
        }
        
        if ($vatBasis < 0 || $vatBasis > 10000) {
            throw new InvalidArgumentException("Geçersiz KDV oranı: {$vatBasis} basis points");
        }
        
        // Integer division - NO FLOAT
        // vat = net * vatBasis / 10000
        $vat = intdiv($netKurus * $vatBasis, 10000);
        
        // Rounding strategy uygulanabilir (gelecek için hazır)
        // Şu an integer division zaten HALF_UP gibi davranır
        
        return $vat;
    }
    
    /**
     * Fatura hesaplama - FULL PIPELINE (STATELESS)
     * 
     * NO DEPENDENCIES:
     * - No global config
     * - No session
     * - No database
     * 
     * Pure function: input → output
     * 
     * Pipeline:
     * 1. Net fiyatları normalize et
     * 2. Satır indirimlerini uygula
     * 3. Global indirimi dağıt (DiscountEngine)
     * 4. Her satır için KDV hesapla
     * 5. Telafi algoritması uygula
     * 
     * @param array $lineItems Satır kalemleri
     * @param string $inputType 'net' veya 'gross'
     * @param int $globalDiscountKurus Global indirim (kuruş)
     * @param string $roundingStrategy Rounding strategy (default: HALF_UP)
     * @param bool $auditMode Enable audit trail?
     * @return array Hesaplama sonuçları
     * 
     * @example
     * $lineItems = [
     *     [
     *         'unit_price' => 10000,
     *         'quantity' => 2,
     *         'vat_rate_basis' => 2000,
     *         'line_discount' => 500,
     *         'urun_id' => 1
     *     ]
     * ];
     * $result = TaxEngine::calculateInvoice($lineItems, 'net', 1000, 'HALF_UP', true);
     */
    public static function calculateInvoice(
        array $lineItems, 
        string $inputType = 'net',
        int $globalDiscountKurus = 0,
        string $roundingStrategy = 'HALF_UP',
        bool $auditMode = false
    ): array {
        if (empty($lineItems)) {
            return [
                'lines' => [],
                'total_net' => 0,
                'total_vat' => 0,
                'total_gross' => 0,
                'global_discount' => 0,
                'currency' => 'TRY'
            ];
        }
        
        $lines = [];
        $totalNetBeforeDiscount = 0;
        
        // PHASE 1: Net fiyatları normalize et
        foreach ($lineItems as $index => $item) {
            $unitPriceInput = (int) $item['unit_price'];
            $quantity = (int) $item['quantity'];
            $vatBasis = (int) $item['vat_rate_basis'];
            $lineDiscount = (int) ($item['line_discount'] ?? 0);
            
            // Validation
            if ($quantity <= 0) {
                throw new InvalidArgumentException("Miktar pozitif olmalı: satır {$index}");
            }
            
            // Net birim fiyatı belirle
            if ($inputType === 'gross') {
                $unitNetKurus = self::calculateNetFromGross($unitPriceInput, $vatBasis);
            } else {
                $unitNetKurus = $unitPriceInput;
            }
            
            // Satır net toplamı
            $lineNetBeforeDiscount = $unitNetKurus * $quantity;
            
            // Satır indirimi uygula
            $lineNetAfterLineDiscount = $lineNetBeforeDiscount - $lineDiscount;
            
            if ($lineNetAfterLineDiscount < 0) {
                throw new InvalidArgumentException("Satır indirimi toplam tutardan fazla olamaz: satır {$index}");
            }
            
            $lines[] = [
                'index' => $index,
                'unit_price_net' => $unitNetKurus,
                'quantity' => $quantity,
                'vat_rate_basis' => $vatBasis,
                'line_net_before_discount' => $lineNetBeforeDiscount,
                'line_discount' => $lineDiscount,
                'line_net_after_line_discount' => $lineNetAfterLineDiscount,
                'distributed_discount' => 0,
                'line_net_final' => $lineNetAfterLineDiscount,
                'line_vat' => 0,
                'line_gross' => 0,
                'compensation' => 0,
                'urun_id' => $item['urun_id'] ?? null
            ];
            
            $totalNetBeforeDiscount += $lineNetAfterLineDiscount;
        }
        
        // PHASE 2: Global indirimi dağıt
        if ($globalDiscountKurus > 0) {
            require_once __DIR__ . '/DiscountEngine.php';
            $lines = DiscountEngine::distributeGlobalDiscount(
                $lines, 
                $globalDiscountKurus, 
                $totalNetBeforeDiscount
            );
        }
        
        // PHASE 3: Her satır için KDV hesapla
        $totalNet = 0;
        $totalVat = 0;
        
        foreach ($lines as &$line) {
            $lineVat = self::calculateVatFromNet($line['line_net_final'], $line['vat_rate_basis']);
            $line['line_vat'] = $lineVat;
            $line['line_gross'] = $line['line_net_final'] + $lineVat;
            
            $totalNet += $line['line_net_final'];
            $totalVat += $lineVat;
        }
        unset($line);
        
        // PHASE 4: KDV telafi algoritması
        $lines = self::applyVatCompensation($lines);
        
        // Telafi sonrası toplam KDV'yi yeniden hesapla
        $totalVat = array_sum(array_column($lines, 'line_vat'));
        $totalGross = $totalNet + $totalVat;
        
        $result = [
            'lines' => $lines,
            'total_net' => $totalNet,
            'total_vat' => $totalVat,
            'total_gross' => $totalGross,
            'global_discount' => $globalDiscountKurus,
            'currency' => 'TRY',
            'metadata' => [
                'input_type' => $inputType,
                'rounding_strategy' => $roundingStrategy,
                'engine_version' => '3.0.0',
                'calculation_timestamp' => time()
            ]
        ];
        
        // Audit mode: Add detailed trace
        if ($auditMode) {
            require_once __DIR__ . '/TaxSnapshot.php';
            $result['audit_trace'] = TaxSnapshot::create($result, [
                'input_type' => $inputType,
                'rounding_strategy' => $roundingStrategy
            ]);
        }
        
        return $result;
    }
    
    /**
     * KDV Telafi Algoritması (E-Fatura Uyumlu)
     * 
     * EN BÜYÜK SATIRA telafi uygula (ERP best practice)
     * 
     * Neden en büyük satır?
     * - Dağılım daha doğal görünür
     * - Audit sırasında daha mantıklı
     * - Küçük satırlarda orantısız değişim olmaz
     * 
     * @param array $lines Hesaplanmış satırlar
     * @return array Telafi uygulanmış satırlar
     */
    private static function applyVatCompensation(array $lines): array
    {
        if (empty($lines)) {
            return $lines;
        }
        
        // KDV oranına göre grupla
        $vatGroups = [];
        foreach ($lines as $line) {
            $basis = $line['vat_rate_basis'];
            if (!isset($vatGroups[$basis])) {
                $vatGroups[$basis] = [
                    'lines' => [],
                    'sum_line_vat' => 0,
                    'sum_line_net' => 0
                ];
            }
            $vatGroups[$basis]['lines'][] = $line['index'];
            $vatGroups[$basis]['sum_line_vat'] += $line['line_vat'];
            $vatGroups[$basis]['sum_line_net'] += $line['line_net_final'];
        }
        
        // Her KDV grubu için telafi
        foreach ($vatGroups as $basis => $group) {
            $globalVat = self::calculateVatFromNet($group['sum_line_net'], $basis);
            $difference = $globalVat - $group['sum_line_vat'];
            
            if ($difference != 0) {
                // EN BÜYÜK satırı bul (ERP best practice)
                $largestLineIndex = null;
                $largestNet = 0;
                
                foreach ($group['lines'] as $lineIndex) {
                    if ($lines[$lineIndex]['line_net_final'] > $largestNet) {
                        $largestNet = $lines[$lineIndex]['line_net_final'];
                        $largestLineIndex = $lineIndex;
                    }
                }
                
                // Telafi uygula
                if ($largestLineIndex !== null) {
                    $lines[$largestLineIndex]['line_vat'] += $difference;
                    $lines[$largestLineIndex]['line_gross'] += $difference;
                    $lines[$largestLineIndex]['compensation'] = $difference;
                }
            }
        }
        
        return $lines;
    }
    
    /**
     * KDV oranını validate et
     * 
     * @param int $basisPoints Basis points
     * @return bool Geçerli mi?
     */
    public static function validateVatRate(int $basisPoints): bool
    {
        // Türkiye'de yaygın: %1, %10, %20
        // Ama kullanıcı özel oran girebilir
        return $basisPoints >= 0 && $basisPoints <= 10000; // Max %100
    }
    
    /**
     * Yaygın KDV oranları (Türkiye)
     * 
     * @return array
     */
    public static function getCommonVatRates(): array
    {
        return [
            ['basis' => 100, 'percent' => 1, 'label' => '%1'],
            ['basis' => 1000, 'percent' => 10, 'label' => '%10'],
            ['basis' => 2000, 'percent' => 20, 'label' => '%20'],
        ];
    }
}
