<?php

namespace Modules\Vrc\Tests\Unit;

use Modules\Vrc\Services\Contracts\TaxServiceContract;
use Modules\Vrc\Services\Finance\TotalsBuilder;
use PHPUnit\Framework\TestCase;

/**
 * Pure unit tests for the totals builder (spec §6.4, §9). The ERP tax engine
 * is stubbed so the arithmetic is verified deterministically without a DB:
 * tax_rate_id 1 → 14% (Egypt VAT), 2 → 15% (KSA VAT), anything else → 0%.
 */
class TotalsBuilderTest extends TestCase
{
    private function builder(): TotalsBuilder
    {
        $tax = new class implements TaxServiceContract {
            public function percentageFor(int $businessId, ?int $taxRateId): float
            {
                return match ($taxRateId) {
                    1 => 14.0,
                    2 => 15.0,
                    default => 0.0,
                };
            }
        };

        return new TotalsBuilder($tax);
    }

    public function test_single_taxable_line(): void
    {
        $b = $this->builder();
        $line = $b->line(1, ['qty' => 2, 'unit_price' => 100, 'tax_rate_id' => 1]);

        $this->assertSame(200.0, $line['line_subtotal']);
        $this->assertSame(0.0, $line['line_discount']);
        $this->assertSame(28.0, $line['line_tax']);   // 14% of 200
        $this->assertSame(228.0, $line['line_total']);
    }

    public function test_line_with_fixed_discount_then_tax(): void
    {
        $b = $this->builder();
        // 200 - 50 = 150 taxable; 14% = 21; total 171
        $line = $b->line(1, ['qty' => 2, 'unit_price' => 100, 'discount' => 50, 'tax_rate_id' => 1]);

        $this->assertSame(50.0, $line['line_discount']);
        $this->assertSame(21.0, $line['line_tax']);
        $this->assertSame(171.0, $line['line_total']);
    }

    public function test_line_with_percentage_discount(): void
    {
        $b = $this->builder();
        // 400 - 10% (40) = 360 taxable; 15% = 54; total 414
        $line = $b->line(1, [
            'qty' => 4, 'unit_price' => 100, 'discount' => 10,
            'discount_type' => 'percentage', 'tax_rate_id' => 2,
        ]);

        $this->assertSame(40.0, $line['line_discount']);
        $this->assertSame(54.0, $line['line_tax']);
        $this->assertSame(414.0, $line['line_total']);
    }

    public function test_non_taxable_line(): void
    {
        $b = $this->builder();
        $line = $b->line(1, ['qty' => 1, 'unit_price' => 100]); // no tax_rate_id

        $this->assertSame(0.0, $line['line_tax']);
        $this->assertSame(100.0, $line['line_total']);
    }

    public function test_document_totals_aggregate_lines(): void
    {
        $b = $this->builder();
        $totals = $b->build(1, [
            ['qty' => 1, 'unit_price' => 100, 'tax_rate_id' => 1],  // sub 100, tax 14
            ['qty' => 2, 'unit_price' => 50, 'tax_rate_id' => 1],   // sub 100, tax 14
            ['qty' => 1, 'unit_price' => 200],                      // sub 200, tax 0
        ]);

        $this->assertSame(400.0, $totals['subtotal']);
        $this->assertSame(0.0, $totals['discount_total']);
        $this->assertSame(28.0, $totals['tax_total']);
        $this->assertSame(428.0, $totals['grand_total']);
    }

    public function test_document_level_discount(): void
    {
        $b = $this->builder();
        // One non-taxable line of 1000, doc discount 10% = 100 → grand 900.
        $totals = $b->build(1, [
            ['qty' => 1, 'unit_price' => 1000],
        ], ['discount' => 10, 'discount_type' => 'percentage']);

        $this->assertSame(1000.0, $totals['subtotal']);
        $this->assertSame(100.0, $totals['discount_total']);
        $this->assertSame(0.0, $totals['tax_total']);
        $this->assertSame(900.0, $totals['grand_total']);
    }

    public function test_discount_cannot_exceed_subtotal(): void
    {
        $b = $this->builder();
        $line = $b->line(1, ['qty' => 1, 'unit_price' => 100, 'discount' => 500]);

        $this->assertSame(100.0, $line['line_discount']); // capped at subtotal
        $this->assertSame(0.0, $line['line_total']);
    }
}
