<?php

namespace App\Tests\Representation;

use App\Config\Repository\SiteConfigRepository;
use App\Payment\Entity\Payment;
use App\Representation\Entity\Representation;
use App\Representation\Service\DomainContextResolver;
use App\Settlement\Repository\FinancialBreakdownRepository;
use App\Settlement\Service\CommissionService;
use App\Tests\ApiTestCase;

/**
 * قانون کمیسیون دامنه‌محور: کمیسیون فقط وقتی ثبت می‌شود که خرید از دامنه‌ی نماینده
 * انجام شده باشد و پزشک/کلینیک هم متعلق به همان نماینده باشد. DomainContextResolver
 * تنها نقطه‌ی نگاشت دامنه است.
 */
class DomainCommissionTest extends ApiTestCase
{
    private function makeRep(?string $domain = null, bool $global = false, bool $active = true): Representation
    {
        $owner = $this->createUser(['ROLE_USER', 'ROLE_REPRESENTATION']);
        $rep = new Representation($owner, 'نماینده دامنه');
        $rep->setCommissionPercent('10');
        if ($domain !== null) $rep->setDomain($domain);
        $rep->setIsGlobal($global);
        $rep->setActive($active);
        $this->em->persist($rep);
        $this->em->flush();

        return $rep;
    }

    private function makePayment(string $frontendAddress): Payment
    {
        $payment = new Payment($this->createUser(), 2_000_000, 'mock', Payment::TYPE_APPOINTMENT, $frontendAddress);
        $this->em->persist($payment);
        $this->em->flush();

        return $payment;
    }

    private function resolver(): DomainContextResolver
    {
        return static::getContainer()->get(DomainContextResolver::class);
    }

    // ── DomainContextResolver ────────────────────────────────────────────────

    public function testResolverMatchesRepresentationDomainWithNormalization(): void
    {
        $domain = 'rep-' . uniqid() . '.ir';
        $rep    = $this->makeRep($domain, global: true);

        $ctx = $this->resolver()->resolve('https://www.' . $domain . ':443/payment/result');

        $this->assertSame($rep->getId(), $ctx->representationId());
        $this->assertTrue($ctx->isGlobalRepresentation);
        $this->assertNull($ctx->city);
    }

    public function testResolverIgnoresInactiveRepresentation(): void
    {
        $domain = 'rep-' . uniqid() . '.ir';
        $this->makeRep($domain, active: false);

        $ctx = $this->resolver()->resolve($domain);

        $this->assertNull($ctx->representation);
        $this->assertFalse($ctx->isGlobalRepresentation);
    }

    public function testResolverUnknownDomainIsEmpty(): void
    {
        $ctx = $this->resolver()->resolve('nowhere-' . uniqid() . '.ir');

        $this->assertNull($ctx->representation);
        $this->assertNull($ctx->city);
    }

    public function testResolverMatchesByFirstLabelForLocalDev(): void
    {
        $prefix = 'repdev' . substr(uniqid(), -6);
        $rep    = $this->makeRep($prefix . '.ir', global: true);

        // host لوکال با TLD متفاوت (`.localhost`) باید همان نماینده را بیابد.
        $ctx = $this->resolver()->resolve($prefix . '.localhost');

        $this->assertSame($rep->getId(), $ctx->representationId());
        $this->assertTrue($ctx->isGlobalRepresentation);
    }

    // ── CommissionService: گارد دوشرطی ───────────────────────────────────────

    public function testAppointmentCommissionOnlyWhenDomainOwnerMatchesDoctorOwner(): void
    {
        static::getContainer()->get(SiteConfigRepository::class)->set('appointment_commission_enabled', '1');
        $commission = static::getContainer()->get(CommissionService::class);
        $breakdowns = static::getContainer()->get(FinancialBreakdownRepository::class);

        $rep   = $this->makeRep('rep-' . uniqid() . '.ir');
        $other = $this->makeRep('rep-' . uniqid() . '.ir');

        // دامنه‌ی نماینده‌ی دیگر → بدون کمیسیون
        $p1 = $this->makePayment('https://' . $other->getDomain() . '/payment/result');
        $commission->processAppointment($p1, $rep->getId(), $other->getId(), 7);
        $this->assertFalse($breakdowns->existsForPayment($p1));

        // بدون دامنه (پرداخت بدون frontend_address) → بدون کمیسیون
        $p2 = $this->makePayment('');
        $commission->processAppointment($p2, $rep->getId(), null, 7);
        $this->assertFalse($breakdowns->existsForPayment($p2));

        // دامنه و مالک یکی → کمیسیون ثبت می‌شود
        $p3 = $this->makePayment('https://' . $rep->getDomain() . '/payment/result');
        $commission->processAppointment($p3, $rep->getId(), $rep->getId(), 7);
        $this->assertTrue($breakdowns->existsForPayment($p3));
    }

    public function testSubscriptionCommissionUsesSameDomainGuard(): void
    {
        $config = static::getContainer()->get(SiteConfigRepository::class);
        $config->set('upgrade_commission_enabled', '1');
        $config->set('upgrade_commission_percent', '20');
        $commission = static::getContainer()->get(CommissionService::class);
        $breakdowns = static::getContainer()->get(FinancialBreakdownRepository::class);

        $rep = $this->makeRep('rep-' . uniqid() . '.ir');

        // نماینده‌ی دامنه معلوم نیست → بدون کمیسیون (رفتار قدیمی کمیسیون می‌داد)
        $p1 = $this->makePayment('');
        $commission->processSubscription($p1, $rep->getId(), null, 5, null);
        $this->assertFalse($breakdowns->existsForPayment($p1));

        // دامنه و مالک یکی → کمیسیون
        $p2 = $this->makePayment('https://' . $rep->getDomain() . '/panel');
        $commission->processSubscription($p2, $rep->getId(), $rep->getId(), 5, null);
        $this->assertTrue($breakdowns->existsForPayment($p2));
    }
}
