<?php

namespace App\Billing\Service;

use App\Billing\Entity\Invoice;
use App\Billing\Entity\InvoiceItem;
use App\Billing\Repository\InvoiceRepository;
use App\Billing\ValueObject\Money;
use App\ClinicService\Service\TariffService;
use App\Insurance\Service\TenantInsuranceService;
use App\Patient\Entity\PatientSession;

class InvoiceService
{
    public function __construct(
        private readonly InvoiceRepository        $invoiceRepo,
        private readonly TariffService            $tariffService,
        private readonly TenantInsuranceService   $tenantInsuranceService,
        private readonly BillingCalculator        $calculator,
    ) {}

    /**
     * ساخت Invoice از یک Encounter (PatientSession).
     * تعرفه‌ی هر خدمت از Tariff سال جاری (با fallback)، پوشش از قرارداد بیمه‌ی tenant.
     * ویزیت به‌عنوان یک آیتم جداگانه با همان قانون پوشش لحاظ می‌شود.
     */
    public function createFromSession(PatientSession $session, string $entityType, int $entityId): Invoice
    {
        $existing = $session->getId() !== null ? $this->invoiceRepo->findBySession($session->getId()) : null;
        if ($existing !== null) {
            return $existing;
        }

        $invoice = new Invoice($entityType, $entityId);
        $invoice->setPatientSessionId($session->getId())
            ->setPatientRecordId($session->getRecord()->getId())
            ->setBaseInsuranceId($session->getInsuranceBaseId())
            ->setSupplementaryInsuranceId($session->getInsuranceSupplementaryId());

        $baseId = $session->getInsuranceBaseId();
        $suppId = $session->getInsuranceSupplementaryId();

        // ویزیت
        $visitPrice = $session->getVisitPriceRials();
        if ($visitPrice > 0) {
            $baseRule = $this->tenantInsuranceService->coverageRule($entityType, $entityId, $baseId);
            $suppRule = $this->tenantInsuranceService->coverageRule($entityType, $entityId, $suppId);
            $breakdown = $this->calculator->calculateItem(new Money($visitPrice), $baseRule, $suppRule);
            $invoice->addItem(new InvoiceItem($invoice, 'ویزیت', $visitPrice, 1, $breakdown, null));
        }

        // خدمات
        foreach ($session->getServices() as $sessionService) {
            $item       = $sessionService->getServiceItem();
            $qty        = max(1, $sessionService->getQuantity());
            $unitPrice  = $this->tariffService->resolvePrice($item);
            $total      = new Money($unitPrice * $qty);

            $baseRule = $this->tenantInsuranceService->coverageRuleForService($entityType, $entityId, $baseId, $item->getId());
            $suppRule = $this->tenantInsuranceService->coverageRuleForService($entityType, $entityId, $suppId, $item->getId());

            $breakdown = $this->calculator->calculateItem($total, $baseRule, $suppRule);
            $invoice->addItem(new InvoiceItem($invoice, $item->getName(), $unitPrice, $qty, $breakdown, $item->getId()));
        }

        $invoice->recalculateTotals();
        $this->invoiceRepo->save($invoice);

        return $invoice;
    }

    public function finalize(Invoice $invoice): void
    {
        $invoice->finalize();
        $this->invoiceRepo->save($invoice);
    }
}
