<?php

namespace Tests\Feature;

use App\Models\Administration;
use App\Models\User;
use App\Services\Admin\Contracts\AdminServiceInterface;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class AdminUserListStatsTest extends TestCase
{
    use RefreshDatabase;

    private AdminServiceInterface $adminService;

    protected function setUp(): void
    {
        parent::setUp();
        $this->adminService = $this->app->make(AdminServiceInterface::class);
    }

    public function test_user_list_stats_displays_correct_sent_and_received_cards(): void
    {
        // 1. Create mock users
        $userA = User::create([
            'msnv'        => 1001,
            'name'        => 'User A',
            'mail'        => 'usera@example.com',
            'pass'        => md5('password'),
            'departments' => 1,
            'role'        => User::ROLE_MEMBER,
            'status'      => User::STATUS_ACTIVE,
            'card'        => 10,
            'flag_send'   => User::FLAG_SEND_ENABLED,
            'first_login' => User::FIRST_LOGIN_FALSE,
        ]);

        $userB = User::create([
            'msnv'        => 1002,
            'name'        => 'User B',
            'mail'        => 'userb@example.com',
            'pass'        => md5('password'),
            'departments' => 1,
            'role'        => User::ROLE_MEMBER,
            'status'      => User::STATUS_ACTIVE,
            'card'        => 10,
            'flag_send'   => User::FLAG_SEND_ENABLED,
            'first_login' => User::FIRST_LOGIN_FALSE,
        ]);

        $selectedMonth = '2026-07';
        $testDate = '2026-07-15';

        // 2. Create mock transaction logs in administration table
        // A sends 3 cards to B
        Administration::create([
            'msnv'     => 1001,
            'received' => 0,
            'sender'   => null,
            'sent'     => 3,
            'receiver' => 1002,
            'date'     => $testDate,
        ]);

        Administration::create([
            'msnv'     => 1002,
            'received' => 3,
            'sender'   => 1001,
            'sent'     => 0,
            'receiver' => null,
            'date'     => $testDate,
        ]);

        // 3. Fetch statistics via AdminService
        $stats = $this->adminService->getUserListWithStats($selectedMonth);

        $users = $stats['users'];
        $topReceived = $stats['topReceivedUser'];
        $topSent = $stats['topSentUser'];

        // Find users in the paginated collection
        $userAResult = collect($users->items())->firstWhere('msnv', 1001);
        $userBResult = collect($users->items())->firstWhere('msnv', 1002);

        $this->assertNotNull($userAResult);
        $this->assertNotNull($userBResult);

        // Assert card counts
        $this->assertEquals(3, $userAResult->total_sent);
        $this->assertEquals(0, $userAResult->total_received);

        $this->assertEquals(0, $userBResult->total_sent);
        $this->assertEquals(3, $userBResult->total_received);

        // Assert top users
        $this->assertEquals(1002, $topReceived->msnv);
        $this->assertEquals(3, $topReceived->total_received);

        $this->assertEquals(1001, $topSent->msnv);
        $this->assertEquals(3, $topSent->total_sent);
    }

    public function test_user_transactions_history_displays_correct_records(): void
    {
        $userA = User::create([
            'msnv'        => 1001,
            'name'        => 'User A',
            'mail'        => 'usera@example.com',
            'pass'        => md5('password'),
            'departments' => 1,
            'role'        => User::ROLE_MEMBER,
            'status'      => User::STATUS_ACTIVE,
            'card'        => 10,
            'flag_send'   => User::FLAG_SEND_ENABLED,
            'first_login' => User::FIRST_LOGIN_FALSE,
        ]);

        $selectedMonth = '2026-07';
        $testDate = '2026-07-15';

        // 1. Create a send record
        Administration::create([
            'msnv'     => 1001,
            'received' => 0,
            'sender'   => null,
            'sent'     => 3,
            'receiver' => 1002,
            'date'     => $testDate,
        ]);

        // 2. Create a receive record
        Administration::create([
            'msnv'     => 1001,
            'received' => 5,
            'sender'   => 1003,
            'sent'     => 0,
            'receiver' => null,
            'date'     => $testDate,
        ]);

        $transactions = $this->adminService->getUserTransactions(1001, $selectedMonth);

        $this->assertCount(2, $transactions->items());

        // Assert specific transaction fields
        $sendTx = collect($transactions->items())->firstWhere('sent', 3);
        $receiveTx = collect($transactions->items())->firstWhere('received', 5);

        $this->assertNotNull($sendTx);
        $this->assertNotNull($receiveTx);

        $this->assertEquals(1002, $sendTx->receiver);
        $this->assertNull($sendTx->sender);

        $this->assertEquals(1003, $receiveTx->sender);
        $this->assertNull($receiveTx->receiver);
    }

    public function test_user_list_stats_filters_by_search_query(): void
    {
        // 1. Create mock users
        User::create([
            'msnv'        => 2001,
            'name'        => 'DEV ALPHA',
            'mail'        => 'alpha@example.com',
            'pass'        => md5('password'),
            'departments' => 1,
            'role'        => User::ROLE_MEMBER,
            'status'      => User::STATUS_ACTIVE,
            'card'        => 10,
            'flag_send'   => User::FLAG_SEND_ENABLED,
            'first_login' => User::FIRST_LOGIN_FALSE,
        ]);

        User::create([
            'msnv'        => 2002,
            'name'        => 'DEV BETA',
            'mail'        => 'beta@example.com',
            'pass'        => md5('password'),
            'departments' => 1,
            'role'        => User::ROLE_MEMBER,
            'status'      => User::STATUS_ACTIVE,
            'card'        => 10,
            'flag_send'   => User::FLAG_SEND_ENABLED,
            'first_login' => User::FIRST_LOGIN_FALSE,
        ]);

        // 2. Fetch statistics via AdminService with search for '2001' (msnv)
        $stats = $this->adminService->getUserListWithStats('2026-07', '2001');
        $users = $stats['users'];

        $this->assertCount(1, $users->items());
        $this->assertEquals(2001, $users->items()[0]->msnv);

        // 3. Fetch statistics via AdminService with search for 'beta@example.com' (mail)
        $stats2 = $this->adminService->getUserListWithStats('2026-07', 'beta@example.com');
        $users2 = $stats2['users'];

        $this->assertCount(1, $users2->items());
        $this->assertEquals(2002, $users2->items()[0]->msnv);
    }

    public function test_user_list_stats_filters_by_flag_send(): void
    {
        // 1. Create mock users
        User::create([
            'msnv'        => 3001,
            'name'        => 'DEV ENABLED',
            'mail'        => 'enabled@example.com',
            'pass'        => md5('password'),
            'departments' => 1,
            'role'        => User::ROLE_MEMBER,
            'status'      => User::STATUS_ACTIVE,
            'card'        => 10,
            'flag_send'   => User::FLAG_SEND_ENABLED,
            'first_login' => User::FIRST_LOGIN_FALSE,
        ]);

        User::create([
            'msnv'        => 3002,
            'name'        => 'DEV DISABLED',
            'mail'        => 'disabled@example.com',
            'pass'        => md5('password'),
            'departments' => 1,
            'role'        => User::ROLE_MEMBER,
            'status'      => User::STATUS_ACTIVE,
            'card'        => 10,
            'flag_send'   => User::FLAG_SEND_DISABLED,
            'first_login' => User::FIRST_LOGIN_FALSE,
        ]);

        // 2. Fetch statistics via AdminService with flag_send = '1'
        $stats = $this->adminService->getUserListWithStats('2026-07', null, '1');
        $users = collect($stats['users']->items());
        $this->assertTrue($users->contains('msnv', 3001));
        $this->assertFalse($users->contains('msnv', 3002));

        // 3. Fetch statistics via AdminService with flag_send = '0'
        $stats2 = $this->adminService->getUserListWithStats('2026-07', null, '0');
        $users2 = collect($stats2['users']->items());
        $this->assertTrue($users2->contains('msnv', 3002));
        $this->assertFalse($users2->contains('msnv', 3001));
    }
}
