<?php

namespace App\Tests\Billing;

use App\Billing\Service\BillingCalculator;
use App\Billing\ValueObject\Money;
use App\Insurance\ValueObject\CoverageRule;
use PHPUnit\Framework\TestCase;

class BillingCalculatorTest extends TestCase
{
    private BillingCalculator $calc;

    protected function setUp(): void
    {
        $this->calc = new BillingCalculator();
    }

    public function testNoInsuranceAllPatient(): void
    {
        $b = $this->calc->calculateItem(new Money(600_000), null, null);
        $this->assertSame(600_000, $b->patientRials);
        $this->assertSame(0, $b->baseInsuranceRials);
        $this->assertSame(0, $b->supplementaryRials);
    }

    public function testBaseAndSupplementary(): void
    {
        // کل 600,000؛ پایه 70% → 420,000؛ مکمل روی 180,000 با ~66.667% → 120,000؛ بیمار 60,000
        $base = new CoverageRule(coveragePercent: 70, franchiseRials: 0, ceilingRials: null);
        $supp = new CoverageRule(coveragePercent: 66.6667, franchiseRials: 0, ceilingRials: null);

        $b = $this->calc->calculateItem(new Money(600_000), $base, $supp);

        $this->assertSame(420_000, $b->baseInsuranceRials);
        $this->assertSame(120_000, $b->supplementaryRials);
        $this->assertSame(60_000, $b->patientRials);
        $this->assertSame(
            $b->totalRials,
            $b->baseInsuranceRials + $b->supplementaryRials + $b->patientRials
        );
    }

    public function testBaseOnly(): void
    {
        $base = new CoverageRule(coveragePercent: 70, franchiseRials: 0, ceilingRials: null);
        $b = $this->calc->calculateItem(new Money(600_000), $base, null);
        $this->assertSame(420_000, $b->baseInsuranceRials);
        $this->assertSame(0, $b->supplementaryRials);
        $this->assertSame(180_000, $b->patientRials);
    }

    public function testBaseCeilingCapsShare(): void
    {
        // پایه 70% = 420,000 ولی سقف 300,000 → بیمار باقی را می‌دهد
        $base = new CoverageRule(coveragePercent: 70, franchiseRials: 0, ceilingRials: 300_000);
        $b = $this->calc->calculateItem(new Money(600_000), $base, null);
        $this->assertSame(300_000, $b->baseInsuranceRials);
        $this->assertSame(300_000, $b->patientRials);
    }

    public function testFranchiseAddedToPatient(): void
    {
        // پایه 100% ولی فرانشیز 50,000 سهم بیمار
        $base = new CoverageRule(coveragePercent: 100, franchiseRials: 50_000, ceilingRials: null);
        $b = $this->calc->calculateItem(new Money(600_000), $base, null);
        $this->assertSame(50_000, $b->patientRials);
        $this->assertSame(600_000, $b->baseInsuranceRials);
    }

    public function testNotCoveredRule(): void
    {
        $b = $this->calc->calculateItem(new Money(600_000), CoverageRule::notCovered(), CoverageRule::notCovered());
        $this->assertSame(600_000, $b->patientRials);
        $this->assertSame(0, $b->baseInsuranceRials);
    }
}
