<?php

declare(strict_types=1);

namespace Bot\Tests\Integration;

use Bot\Domain\Entity\Payment;
use Bot\Domain\Entity\User;
use Bot\Domain\Repository\PaymentRepositoryInterface;
use Bot\Domain\Repository\UserRepositoryInterface;
use Bot\Domain\Service\PaymentService;
use Bot\Domain\Service\UserService;
use Bot\Infrastructure\Repository\InMemoryPaymentRepository;
use Bot\Infrastructure\Repository\InMemoryUserRepository;
use PHPUnit\Framework\TestCase;

/**
 * تست یکپارچه سبک برای سناریو پرداخت موفق
 */
final class PaymentSuccessTest extends TestCase
{
    private UserRepositoryInterface $userRepository;
    private PaymentRepositoryInterface $paymentRepository;
    private UserService $userService;
    private PaymentService $paymentService;

    protected function setUp(): void
    {
        $this->userRepository = new InMemoryUserRepository();
        $this->paymentRepository = new InMemoryPaymentRepository();
        $this->userService = new UserService($this->userRepository);
        $this->paymentService = new PaymentService($this->paymentRepository);
    }

    public function testSuccessfulPaymentViaTelegramStars(): void
    {
        // ایجاد کاربر
        $user = $this->userService->getOrCreateByTelegramId(12345);
        $this->assertEquals('free', $user->getMode());

        // کاربر پرداخت را شروع می‌کند
        $payment = $this->paymentService->createPending(
            $user,
            'telegram_stars',
            1000,
            'stars_payload_123'
        );

        $this->assertEquals(Payment::STATUS_PENDING, $payment->getStatus());

        // پرداخت با موفقیت کامل می‌شود
        $externalId = 'stars_txn_12345';
        $this->paymentService->markSuccess($payment, $externalId);

        // بررسی وضعیت پرداخت
        $this->assertEquals(Payment::STATUS_SUCCESS, $payment->getStatus());
        $this->assertEquals($externalId, $payment->getExternalId());

        // کاربر به پریمیوم ارتقا می‌یابد
        $this->userService->upgradeToPremium($user);
        $this->assertEquals('premium', $user->getMode());
    }

    public function testSuccessfulPaymentViaNextPay(): void
    {
        // ایجاد کاربر
        $user = $this->userService->getOrCreateByTelegramId(12345);

        // ایجاد پرداخت
        $payment = $this->paymentService->createPending(
            $user,
            'nextpay',
            50000,
            'nextpay_payload_456'
        );

        // Callback از NextPay دریافت می‌شود
        $externalId = 'nextpay_ref_789';
        $this->paymentService->markSuccess($payment, $externalId);

        // بررسی پرداخت
        $foundPayment = $this->paymentService->findByExternalId($externalId);
        $this->assertNotNull($foundPayment);
        $this->assertEquals(Payment::STATUS_SUCCESS, $foundPayment->getStatus());
        $this->assertEquals('nextpay', $foundPayment->getGateway());
    }

    public function testSuccessfulPaymentViaZarinPal(): void
    {
        // ایجاد کاربر
        $user = $this->userService->getOrCreateByTelegramId(12345);

        // ایجاد پرداخت
        $payment = $this->paymentService->createPending(
            $user,
            'zarinpal',
            30000,
            'zarinpal_payload_789'
        );

        // Callback از ZarinPal دریافت می‌شود
        $externalId = 'zarinpal_authority_123';
        $this->paymentService->setExternalId($payment, $externalId);
        $this->paymentService->markSuccess($payment, $externalId);

        // بررسی پرداخت
        $foundPayment = $this->paymentService->findByPayload('zarinpal_payload_789');
        $this->assertNotNull($foundPayment);
        $this->assertEquals(Payment::STATUS_SUCCESS, $foundPayment->getStatus());
        $this->assertEquals($externalId, $foundPayment->getExternalId());
    }

    public function testPaymentFailure(): void
    {
        // ایجاد کاربر
        $user = $this->userService->getOrCreateByTelegramId(12345);
        $this->assertEquals('free', $user->getMode());

        // ایجاد پرداخت
        $payment = $this->paymentService->createPending(
            $user,
            'telegram_stars',
            1000
        );

        // پرداخت ناموفق می‌شود
        $this->paymentService->markFailed($payment);

        // بررسی وضعیت پرداخت
        $this->assertEquals(Payment::STATUS_FAILED, $payment->getStatus());

        // کاربر نباید به پریمیوم ارتقا یابد
        $this->assertEquals('free', $user->getMode());
    }
}

