<?php

declare(strict_types=1);

namespace Bot\Tests\Unit;

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

final class PaymentServiceTest extends TestCase
{
    private PaymentRepositoryInterface $paymentRepository;
    private PaymentService $paymentService;
    private InMemoryUserRepository $userRepository;

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

    public function testCreatePendingPayment(): void
    {
        $user = new User(1, 12345);
        $this->userRepository->save($user);

        $payment = $this->paymentService->createPending(
            $user,
            'telegram_stars',
            1000,
            'payload123'
        );

        $this->assertInstanceOf(Payment::class, $payment);
        $this->assertEquals($user->getId(), $payment->getUserId());
        $this->assertEquals('telegram_stars', $payment->getGateway());
        $this->assertEquals(1000, $payment->getAmount());
        $this->assertEquals(Payment::STATUS_PENDING, $payment->getStatus());
        $this->assertEquals('payload123', $payment->getPayload());
    }

    public function testMarkSuccess(): void
    {
        $user = new User(1, 12345);
        $this->userRepository->save($user);

        $payment = $this->paymentService->createPending($user, 'nextpay', 5000);
        $externalId = 'ext_12345';

        $this->paymentService->markSuccess($payment, $externalId);

        $this->assertEquals(Payment::STATUS_SUCCESS, $payment->getStatus());
        $this->assertEquals($externalId, $payment->getExternalId());
    }

    public function testMarkFailed(): void
    {
        $user = new User(1, 12345);
        $this->userRepository->save($user);

        $payment = $this->paymentService->createPending($user, 'zarinpal', 3000);

        $this->paymentService->markFailed($payment);

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

    public function testFindByPayload(): void
    {
        $user = new User(1, 12345);
        $this->userRepository->save($user);

        $payload = 'unique_payload_123';
        $payment = $this->paymentService->createPending($user, 'telegram_stars', 1000, $payload);

        $foundPayment = $this->paymentService->findByPayload($payload);

        $this->assertNotNull($foundPayment);
        $this->assertEquals($payment->getId(), $foundPayment->getId());
    }

    public function testFindByExternalId(): void
    {
        $user = new User(1, 12345);
        $this->userRepository->save($user);

        $payload = 'test_payload_123';
        $payment = $this->paymentService->createPending($user, 'nextpay', 5000, $payload);
        
        // گرفتن payment با ID واقعی از repository
        $savedPayment = $this->paymentService->findByPayload($payload);
        $this->assertNotNull($savedPayment);
        $payment = $savedPayment;
        
        $externalId = 'ext_98765';
        $this->paymentService->markSuccess($payment, $externalId);

        $foundPayment = $this->paymentService->findByExternalId($externalId);

        $this->assertNotNull($foundPayment);
        $this->assertEquals($payment->getId(), $foundPayment->getId());
        $this->assertEquals(Payment::STATUS_SUCCESS, $foundPayment->getStatus());
    }

    public function testSetExternalId(): void
    {
        $user = new User(1, 12345);
        $this->userRepository->save($user);

        $payment = $this->paymentService->createPending($user, 'zarinpal', 3000);
        $externalId = 'zarinpal_123';

        $this->paymentService->setExternalId($payment, $externalId);

        $this->assertEquals($externalId, $payment->getExternalId());
    }
}

