<?php

namespace Tests\Unit;

use App\Http\Controllers\Admin\ActivationRequestAdminController;
use App\Models\ActivationHistory;
use App\Models\User;
use App\Services\ActivationHistoryService;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use PHPUnit\Framework\TestCase;
use ReflectionMethod;
use stdClass;

class ActivationHistorySummaryTest extends TestCase
{
    public function test_auto_verified_summary_matches_history_rules(): void
    {
        $summary = $this->buildHistorySummary(collect([
            $this->makeHistory([
                'event' => 'admin_request_approved',
                'verification_channel' => 'admin_manual',
                'metadata' => [
                    'request_state' => 'linked_pending_request_auto_approved',
                ],
                'happened_at' => Carbon::now(),
            ]),
            $this->makeHistory([
                'event' => 'direct_payment_verified',
                'verification_channel' => 'direct_payment',
                'metadata' => [
                    'auto_verified' => false,
                ],
                'happened_at' => Carbon::now(),
            ]),
            $this->makeHistory([
                'event' => 'voucher_verified',
                'verification_channel' => 'voucher',
                'metadata' => [],
                'happened_at' => Carbon::now(),
            ]),
        ]));

        $this->assertSame(3, $summary['total_verified']);
        $this->assertSame(2, $summary['auto_verified']);
    }

    public function test_outstanding_referral_commissions_keep_only_positive_net_amounts(): void
    {
        $summary = $this->invokeControllerMethod('summarizeOutstandingReferralCommissions', [collect([
            $this->makeIncomeRow(11, 120),
            $this->makeIncomeRow(11, -120),
            $this->makeIncomeRow(22, 80),
            $this->makeIncomeRow(22, -30),
            $this->makeIncomeRow(33, -15),
        ])]);

        $this->assertSame([
            22 => 50.0,
        ], $summary);
    }

    public function test_legacy_voucher_payment_is_detected_and_mapped_into_history_payload(): void
    {
        $payment = [
            'user_id' => 15,
            'amount' => 300,
            'status' => 'completed',
            'payment_method' => 'voucher',
            'transaction_id' => 'ACT-VCH-20260309-ABC123',
            'trx_id' => null,
            'raw_response' => json_encode([
                'channel' => 'voucher',
                'purpose' => 'activation',
                'voucher_balance_before' => 500,
                'voucher_balance_after' => 200,
            ], JSON_UNESCAPED_UNICODE),
            'updated_at' => '2026-03-09 10:30:00',
        ];

        $this->assertTrue($this->invokeControllerMethod('isLegacyAutoVerificationPayment', [$payment]));

        $payload = $this->invokeControllerMethod('buildLegacyAutoVerificationHistoryPayload', [
            $this->makeUser(15, 'Voucher User'),
            $payment,
            99,
        ]);

        $this->assertSame('voucher_verified', $payload['event']);
        $this->assertSame('voucher', $payload['verification_channel']);
        $this->assertSame('user_activation_page', $payload['source']);
        $this->assertSame('linked_pending_request_auto_approved', $payload['metadata']['request_state']);
        $this->assertSame(500, $payload['metadata']['voucher_balance_before']);
        $this->assertSame(200, $payload['metadata']['voucher_balance_after']);
    }

    public function test_legacy_direct_payment_payload_marks_webhook_auto_verification(): void
    {
        $payment = [
            'user_id' => 23,
            'amount' => 300,
            'status' => 'completed',
            'payment_method' => 'bkash',
            'transaction_id' => 'TXN-10001',
            'trx_id' => 'TRX12345',
            'raw_response' => json_encode([
                'transaction_id' => 'TXN-10001',
                'status' => 'COMPLETED',
                'metadata' => [
                    'user_id' => 23,
                    'purpose' => 'activation',
                ],
                'mobile' => '01700000000',
            ], JSON_UNESCAPED_UNICODE),
            'updated_at' => '2026-03-09 11:00:00',
        ];

        $this->assertTrue($this->invokeControllerMethod('isLegacyAutoVerificationPayment', [$payment]));

        $payload = $this->invokeControllerMethod('buildLegacyAutoVerificationHistoryPayload', [
            $this->makeUser(23, 'Payment User'),
            $payment,
            null,
        ]);

        $this->assertSame('direct_payment_verified', $payload['event']);
        $this->assertSame('payment_webhook', $payload['source']);
        $this->assertSame('auto_verified_after_payment_webhook', $payload['metadata']['request_state']);
        $this->assertSame('01700000000', $payload['metadata']['payment_mobile']);
        $this->assertTrue($payload['metadata']['auto_verified']);
    }

    public function test_wallet_recharge_payment_is_not_detected_as_activation_history(): void
    {
        $payment = [
            'user_id' => 44,
            'amount' => 300,
            'status' => 'completed',
            'payment_method' => 'bkash',
            'transaction_id' => 'TXN-20002',
            'trx_id' => 'TRX999',
            'raw_response' => json_encode([
                'verify' => [
                    'metadata' => [
                        'user_id' => 44,
                        'purpose' => 'wallet_recharge',
                    ],
                ],
            ], JSON_UNESCAPED_UNICODE),
        ];

        $this->assertFalse($this->invokeControllerMethod('isLegacyAutoVerificationPayment', [$payment]));
    }

    public function test_completed_payment_with_activation_amount_can_be_detected_without_metadata(): void
    {
        $payment = [
            'user_id' => 51,
            'amount' => 300,
            'status' => 'completed',
            'payment_method' => 'bkash',
            'transaction_id' => 'TXN-30003',
            'trx_id' => 'TRX30003',
            'raw_response' => json_encode([
                'verify' => [
                    'status' => 'COMPLETED',
                ],
            ], JSON_UNESCAPED_UNICODE),
        ];

        $this->assertTrue($this->invokeControllerMethod('isLegacyAutoVerificationPayment', [$payment, [], 300.0]));
        $this->assertFalse($this->invokeControllerMethod('isLegacyAutoVerificationPayment', [$payment, ['TXN-30003' => true], 300.0]));
    }

    public function test_all_trail_summary_counts_auto_admin_and_non_verify_rows(): void
    {
        $summary = $this->invokeControllerMethod('buildAllHistorySummaryFromHistories', [collect([
            $this->makeHistory([
                'event' => 'voucher_verified',
                'verification_channel' => 'voucher',
                'metadata' => [
                    'auto_verified' => true,
                ],
            ]),
            $this->makeHistory([
                'event' => 'admin_manual_verified',
                'verification_channel' => 'admin_manual',
                'metadata' => [
                    'auto_verified' => false,
                ],
            ]),
            $this->makeHistory([
                'event' => 'admin_request_rejected',
                'verification_channel' => 'admin_manual',
                'metadata' => [],
            ]),
            $this->makeHistory([
                'event' => 'admin_manual_unverified',
                'verification_channel' => 'admin_manual',
                'metadata' => [
                    'repair_only' => true,
                ],
            ]),
        ])]);

        $this->assertSame('all', $summary['summary_mode']);
        $this->assertSame(4, $summary['total_trail']);
        $this->assertSame(2, $summary['total_verified']);
        $this->assertSame(1, $summary['auto_verified']);
        $this->assertSame(1, $summary['admin_verified']);
        $this->assertSame(2, $summary['non_verified']);
        $this->assertSame(1, $summary['repair_actions']);
    }

    private function buildHistorySummary(Collection $histories): array
    {
        return $this->invokeControllerMethod('buildHistorySummary', [$histories]);
    }

    private function makeHistory(array $attributes): ActivationHistory
    {
        return new class($attributes) extends ActivationHistory {
            public function __construct(array $attributes = [])
            {
                $this->attributes = $attributes;
            }

            public function getAttribute($key)
            {
                return $this->attributes[$key] ?? null;
            }
        };
    }

    private function makeIncomeRow(int $userId, float $amount): stdClass
    {
        $row = new stdClass();
        $row->user_id = $userId;
        $row->amount = $amount;

        return $row;
    }

    private function makeUser(int $id, string $name): User
    {
        $user = new User();
        $user->forceFill([
            'id' => $id,
            'name' => $name,
            'email' => strtolower(str_replace(' ', '.', $name)) . '@example.com',
            'mobile' => '01800000000',
            'referral_code' => 'REF' . $id,
        ]);

        return $user;
    }

    private function invokeControllerMethod(string $methodName, array $arguments): mixed
    {
        $controller = new ActivationRequestAdminController(new ActivationHistoryService());
        $method = new ReflectionMethod($controller, $methodName);
        $method->setAccessible(true);

        return $method->invokeArgs($controller, $arguments);
    }
}
