<?php
declare(strict_types=1);

namespace Tests\Integration\Payments;

use Tests\DatabaseTestCase;
use Tests\Factories\MemberFactory;
use App\Modules\Payments\Services\PaymentService;

final class PaymentServiceTest extends DatabaseTestCase
{
    public function testProcessPaymentSuccess(): void
    {
        $member = (new MemberFactory($this->db))->create();

        $result = PaymentService::processPayment([
            'member_id' => $member['id'],
            'amount' => '527.00',
            'payment_type' => 'annual_subscription',
            'payment_method' => 'cash',
        ]);

        $this->assertTrue($result['success']);
        $this->assertArrayHasKey('payment_id', $result);
        $this->assertArrayHasKey('receipt_id', $result);
        $this->assertArrayHasKey('receipt_number', $result);
        $this->assertNotEmpty($result['receipt_number']);

        $payment = $this->db->selectOne("SELECT * FROM payments WHERE id = ?", [$result['payment_id']]);
        $this->assertNotNull($payment);
        $this->assertEquals('527.00', $payment['amount']);
        $this->assertEquals('annual_subscription', $payment['payment_type']);
        $this->assertEquals('cash', $payment['payment_method']);
        $this->assertEquals($member['id'], $payment['member_id']);

        $receipt = $this->db->selectOne("SELECT * FROM receipts WHERE id = ?", [$result['receipt_id']]);
        $this->assertNotNull($receipt);
        $this->assertEquals($result['receipt_number'], $receipt['receipt_number']);
        $this->assertEquals('527.00', $receipt['amount']);

        $this->assertEventDispatched('payment.completed', function (array $data) use ($member) {
            $this->assertEquals($member['id'], $data['member_id']);
            $this->assertEquals('527.00', $data['amount']);
            $this->assertEquals('annual_subscription', $data['payment_type']);
            $this->assertEquals('cash', $data['method']);
        });
    }

    public function testProcessPaymentRejectsZeroAmount(): void
    {
        $member = (new MemberFactory($this->db))->create();

        $result = PaymentService::processPayment([
            'member_id' => $member['id'],
            'amount' => '0.00',
            'payment_type' => 'annual_subscription',
        ]);

        $this->assertFalse($result['success']);
        $this->assertArrayHasKey('error', $result);
        $this->assertEventNotDispatched('payment.completed');
    }

    public function testProcessPaymentRejectsEmptyType(): void
    {
        $member = (new MemberFactory($this->db))->create();

        $result = PaymentService::processPayment([
            'member_id' => $member['id'],
            'amount' => '100.00',
            'payment_type' => '',
        ]);

        $this->assertFalse($result['success']);
        $this->assertEventNotDispatched('payment.completed');
    }

    public function testProcessPaymentRejectsNonExistentMember(): void
    {
        $result = PaymentService::processPayment([
            'member_id' => 999999,
            'amount' => '100.00',
            'payment_type' => 'fine',
        ]);

        $this->assertFalse($result['success']);
        $this->assertStringContainsString('غير موجود', $result['error']);
        $this->assertEventNotDispatched('payment.completed');
    }

    public function testProcessPaymentWithCheckMethod(): void
    {
        $member = (new MemberFactory($this->db))->create();

        $result = PaymentService::processPayment([
            'member_id' => $member['id'],
            'amount' => '10000.00',
            'payment_type' => 'membership_fee',
            'payment_method' => 'check',
            'check_number' => 'CHK-001',
            'check_bank' => 'بنك مصر',
            'check_date' => '2026-06-01',
        ]);

        $this->assertTrue($result['success']);

        $payment = $this->db->selectOne("SELECT * FROM payments WHERE id = ?", [$result['payment_id']]);
        $this->assertEquals('check', $payment['payment_method']);
        $this->assertEquals('CHK-001', $payment['check_number']);
        $this->assertEquals('بنك مصر', $payment['check_bank']);
        $this->assertEquals('pending', $payment['check_status']);
    }
}
