<?php
/**
 * TaxEngine Unit Tests
 * 
 * Production-grade KDV hesaplama motorunun test senaryoları
 * 
 * @package Odjoo
 * @category Tests
 * @version 2.0.0
 */

require_once __DIR__ . '/../classes/MoneyHelper.php';
require_once __DIR__ . '/../classes/TaxEngine.php';
require_once __DIR__ . '/../classes/DiscountEngine.php';

class TaxEngineTest
{
    private $testResults = [];
    private $passedTests = 0;
    private $failedTests = 0;
    
    /**
     * Tüm testleri çalıştır
     */
    public function runAllTests()
    {
        echo "==========================================================\n";
        echo "  ODJOO - TAX ENGINE UNIT TESTS\n";
        echo "  Production-Grade KDV Sistemi\n";
        echo "==========================================================\n\n";
        
        $this->testBasisPointConversion();
        $this->testNetFromGross();
        $this->testVatFromNet();
        $this->testSimpleInvoice();
        $this->testVatCompensation();
        $this->testDiscountDistribution();
        $this->testMultipleVatRates();
        $this->testEdgeCases();
        
        $this->printResults();
    }
    
    /**
     * Test 1: Basis Point Dönüşümü
     */
    private function testBasisPointConversion()
    {
        echo "Test 1: Basis Point Dönüşümü\n";
        echo "-----------------------------\n";
        
        // %20 = 2000 basis points
        $basis = TaxEngine::percentToBasis(20.0);
        $this->assert($basis === 2000, "20% = 2000 basis points", $basis);
        
        // 2000 basis points = %20
        $percent = TaxEngine::basisToPercent(2000);
        $this->assert($percent === 20.0, "2000 bp = 20%", $percent);
        
        // %1 = 100 basis points
        $basis = TaxEngine::percentToBasis(1.0);
        $this->assert($basis === 100, "1% = 100 basis points", $basis);
        
        // %10 = 1000 basis points
        $basis = TaxEngine::percentToBasis(10.0);
        $this->assert($basis === 1000, "10% = 1000 basis points", $basis);
        
        echo "\n";
    }
    
    /**
     * Test 2: KDV Dahil'den Net Hesaplama
     */
    private function testNetFromGross()
    {
        echo "Test 2: KDV Dahil'den Net Hesaplama\n";
        echo "------------------------------------\n";
        
        // 120 TL (KDV dahil), %20 KDV → 100 TL (net)
        $gross = 12000; // kuruş
        $vatBasis = 2000; // %20
        $net = TaxEngine::calculateNetFromGross($gross, $vatBasis);
        $this->assert($net === 10000, "120 TL (dahil) → 100 TL (net)", $net);
        
        // 110 TL (KDV dahil), %10 KDV → 100 TL (net)
        $gross = 11000;
        $vatBasis = 1000; // %10
        $net = TaxEngine::calculateNetFromGross($gross, $vatBasis);
        $this->assert($net === 10000, "110 TL (dahil) → 100 TL (net)", $net);
        
        echo "\n";
    }
    
    /**
     * Test 3: Net'ten KDV Hesaplama
     */
    private function testVatFromNet()
    {
        echo "Test 3: Net'ten KDV Hesaplama\n";
        echo "------------------------------\n";
        
        // 100 TL (net), %20 KDV → 20 TL (KDV)
        $net = 10000; // kuruş
        $vatBasis = 2000; // %20
        $vat = TaxEngine::calculateVatFromNet($net, $vatBasis);
        $this->assert($vat === 2000, "100 TL × 20% = 20 TL", $vat);
        
        // 100 TL (net), %10 KDV → 10 TL (KDV)
        $vatBasis = 1000; // %10
        $vat = TaxEngine::calculateVatFromNet($net, $vatBasis);
        $this->assert($vat === 1000, "100 TL × 10% = 10 TL", $vat);
        
        // 100 TL (net), %1 KDV → 1 TL (KDV)
        $vatBasis = 100; // %1
        $vat = TaxEngine::calculateVatFromNet($net, $vatBasis);
        $this->assert($vat === 100, "100 TL × 1% = 1 TL", $vat);
        
        echo "\n";
    }
    
    /**
     * Test 4: Basit Fatura Hesaplama
     */
    private function testSimpleInvoice()
    {
        echo "Test 4: Basit Fatura Hesaplama\n";
        echo "-------------------------------\n";
        
        $lineItems = [
            [
                'unit_price' => 10000, // 100 TL
                'quantity' => 2,
                'vat_rate_basis' => 2000, // %20
                'line_discount' => 0,
                'urun_id' => 1
            ]
        ];
        
        $result = TaxEngine::calculateInvoice($lineItems, 'net', 0);
        
        $this->assert($result['total_net'] === 20000, "Net: 200 TL", $result['total_net']);
        $this->assert($result['total_vat'] === 4000, "KDV: 40 TL", $result['total_vat']);
        $this->assert($result['total_gross'] === 24000, "Brüt: 240 TL", $result['total_gross']);
        
        echo "\n";
    }
    
    /**
     * Test 5: KDV Telafi Algoritması
     */
    private function testVatCompensation()
    {
        echo "Test 5: KDV Telafi Algoritması\n";
        echo "-------------------------------\n";
        
        // 33.33 TL × 3 = 99.99 TL (yuvarlama farkı oluşur)
        $lineItems = [
            [
                'unit_price' => 3333, // 33.33 TL
                'quantity' => 3,
                'vat_rate_basis' => 2000, // %20
                'line_discount' => 0,
                'urun_id' => 1
            ]
        ];
        
        $result = TaxEngine::calculateInvoice($lineItems, 'net', 0);
        
        // Net: 3333 × 3 = 9999 kuruş
        $this->assert($result['total_net'] === 9999, "Net: 99.99 TL", $result['total_net']);
        
        // KDV telafi sonrası toplam KDV doğru olmalı
        $expectedVat = intdiv(9999 * 2000, 10000); // 1999 kuruş
        $this->assert($result['total_vat'] === $expectedVat, "KDV telafi uygulandı", $result['total_vat']);
        
        // En az bir satırda telafi olmalı
        $hasCompensation = false;
        foreach ($result['lines'] as $line) {
            if ($line['compensation'] != 0) {
                $hasCompensation = true;
                break;
            }
        }
        $this->assert($hasCompensation, "Telafi uygulandı", $hasCompensation);
        
        echo "\n";
    }
    
    /**
     * Test 6: İndirim Dağıtımı
     */
    private function testDiscountDistribution()
    {
        echo "Test 6: İndirim Dağıtımı\n";
        echo "------------------------\n";
        
        $lineItems = [
            [
                'unit_price' => 20000, // 200 TL
                'quantity' => 1,
                'vat_rate_basis' => 2000,
                'line_discount' => 0,
                'urun_id' => 1
            ],
            [
                'unit_price' => 10000, // 100 TL
                'quantity' => 1,
                'vat_rate_basis' => 2000,
                'line_discount' => 0,
                'urun_id' => 2
            ]
        ];
        
        $globalDiscount = 5000; // 50 TL
        
        $result = TaxEngine::calculateInvoice($lineItems, 'net', $globalDiscount);
        
        // Toplam indirim doğru dağıtılmalı
        $totalDistributed = 0;
        foreach ($result['lines'] as $line) {
            $totalDistributed += $line['distributed_discount'];
        }
        $this->assert($totalDistributed === $globalDiscount, "İndirim tam dağıtıldı", $totalDistributed);
        
        // Net toplam: 300 - 50 = 250 TL
        $this->assert($result['total_net'] === 25000, "Net (indirim sonrası): 250 TL", $result['total_net']);
        
        echo "\n";
    }
    
    /**
     * Test 7: Çoklu KDV Oranları
     */
    private function testMultipleVatRates()
    {
        echo "Test 7: Çoklu KDV Oranları\n";
        echo "--------------------------\n";
        
        $lineItems = [
            [
                'unit_price' => 10000,
                'quantity' => 1,
                'vat_rate_basis' => 100, // %1
                'line_discount' => 0,
                'urun_id' => 1
            ],
            [
                'unit_price' => 10000,
                'quantity' => 1,
                'vat_rate_basis' => 1000, // %10
                'line_discount' => 0,
                'urun_id' => 2
            ],
            [
                'unit_price' => 10000,
                'quantity' => 1,
                'vat_rate_basis' => 2000, // %20
                'line_discount' => 0,
                'urun_id' => 3
            ]
        ];
        
        $result = TaxEngine::calculateInvoice($lineItems, 'net', 0);
        
        // Toplam KDV: 100 + 1000 + 2000 = 3100 kuruş (31 TL)
        $this->assert($result['total_vat'] === 3100, "Toplam KDV: 31 TL", $result['total_vat']);
        
        // Her oran için ayrı telafi kontrolü
        $vatGroups = [];
        foreach ($result['lines'] as $line) {
            $rate = $line['vat_rate_basis'];
            if (!isset($vatGroups[$rate])) {
                $vatGroups[$rate] = ['vat' => 0, 'net' => 0];
            }
            $vatGroups[$rate]['vat'] += $line['line_vat'];
            $vatGroups[$rate]['net'] += $line['line_net_final'];
        }
        
        $this->assert(count($vatGroups) === 3, "3 farklı KDV oranı", count($vatGroups));
        
        echo "\n";
    }
    
    /**
     * Test 8: Edge Cases
     */
    private function testEdgeCases()
    {
        echo "Test 8: Edge Cases\n";
        echo "------------------\n";
        
        // Sıfır tutar
        $lineItems = [
            [
                'unit_price' => 0,
                'quantity' => 1,
                'vat_rate_basis' => 2000,
                'line_discount' => 0,
                'urun_id' => 1
            ]
        ];
        $result = TaxEngine::calculateInvoice($lineItems, 'net', 0);
        $this->assert($result['total_vat'] === 0, "Sıfır tutar → Sıfır KDV", $result['total_vat']);
        
        // Çok büyük tutar (overflow kontrolü)
        try {
            $lineItems = [
                [
                    'unit_price' => 1000000000, // 10 milyon TL
                    'quantity' => 100,
                    'vat_rate_basis' => 2000,
                    'line_discount' => 0,
                    'urun_id' => 1
                ]
            ];
            $result = TaxEngine::calculateInvoice($lineItems, 'net', 0);
            $this->assert(true, "Büyük tutar işlendi", $result['total_net']);
        } catch (Exception $e) {
            $this->assert(false, "Büyük tutar hatası", $e->getMessage());
        }
        
        echo "\n";
    }
    
    /**
     * Assert helper
     */
    private function assert($condition, $message, $actual = null)
    {
        if ($condition) {
            echo "  ✓ {$message}";
            if ($actual !== null && $actual !== true) {
                echo " → " . $actual;
            }
            echo "\n";
            $this->passedTests++;
        } else {
            echo "  ✗ {$message}";
            if ($actual !== null) {
                echo " → " . var_export($actual, true);
            }
            echo "\n";
            $this->failedTests++;
        }
    }
    
    /**
     * Sonuçları yazdır
     */
    private function printResults()
    {
        echo "\n==========================================================\n";
        echo "  TEST SONUÇLARI\n";
        echo "==========================================================\n";
        echo "  Başarılı: {$this->passedTests}\n";
        echo "  Başarısız: {$this->failedTests}\n";
        echo "  Toplam: " . ($this->passedTests + $this->failedTests) . "\n";
        
        if ($this->failedTests === 0) {
            echo "\n  ✓ TÜM TESTLER BAŞARILI!\n";
        } else {
            echo "\n  ✗ BAZI TESTLER BAŞARISIZ!\n";
        }
        echo "==========================================================\n";
    }
}

// Testleri çalıştır
$tester = new TaxEngineTest();
$tester->runAllTests();
