<?php

namespace App\Billing\Service;

use App\Billing\ValueObject\Money;
use App\Billing\ValueObject\ShareBreakdown;
use App\Insurance\ValueObject\CoverageRule;

class BillingCalculator
{
    /**
     * محاسبه‌ی سهم برای یک آیتم.
     * ترتیب: کل → پوشش پایه (با سقف) → باقیمانده → تعهد مکمل روی باقیمانده منهای فرانشیز (با سقف).
     */
    public function calculateItem(
        Money $total,
        ?CoverageRule $base,
        ?CoverageRule $supplementary,
    ): ShareBreakdown {
        $baseShare = Money::zero();
        $remaining = $total;

        if ($base !== null && $base->covered) {
            $baseShare = $total->percent($base->coveragePercent);
            if ($base->ceilingRials !== null) {
                $baseShare = $baseShare->min(new Money($base->ceilingRials));
            }
            $remaining = $total->sub($baseShare);
        }

        $suppShare = Money::zero();
        if ($supplementary !== null && $supplementary->covered) {
            // فرانشیز سهم اجباری بیمار از همین مبلغ است و از تعهد تکمیلی کسر می‌شود —
            // نه اینکه روی سهم بیمار سوار شود، وگرنه جمع سهم‌ها از کل بیشتر می‌شد و
            // مطالبهٔ ارسالی به بیمه بیش از سهم واقعی‌اش می‌بود.
            $suppShare = $remaining->percent($supplementary->coveragePercent)
                ->sub($remaining->percent($supplementary->franchisePercent));

            if ($supplementary->ceilingRials !== null) {
                $suppShare = $suppShare->min(new Money($supplementary->ceilingRials));
            }
        }

        // بیمهٔ پایه صرفاً درصدی است و فرانشیزش در محاسبه دخالت نمی‌کند.
        $patient = $total->sub($baseShare)->sub($suppShare);

        return new ShareBreakdown(
            totalRials:         $total->rials,
            baseInsuranceRials: $baseShare->rials,
            supplementaryRials: $suppShare->rials,
            patientRials:       $patient->rials,
        );
    }
}
