<?php

namespace Tests\Feature;

use App\Models\BankLog;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class BankControllerTest extends TestCase
{
    use RefreshDatabase;

    public function test_info_returns_balances_and_logs()
    {
        $user = User::factory()->create([
            'jjb' => 1000,
            'bank_jjb' => 5000,
        ]);

        BankLog::create([
            'user_id' => $user->id,
            'type' => 'deposit',
            'amount' => 500,
            'balance_after' => 5000,
        ]);

        $response = $this->actingAs($user)->getJson(route('bank.info'));

        $response->assertStatus(200);
        $response->assertJson([
            'status' => 'success',
            'jjb' => 1000,
            'bank_jjb' => 5000,
        ]);
        $response->assertJsonCount(1, 'logs');
    }

    public function test_deposit_transfers_jjb_to_bank()
    {
        $user = User::factory()->create([
            'jjb' => 1000,
            'bank_jjb' => 0,
        ]);

        $response = $this->actingAs($user)->postJson(route('bank.deposit'), [
            'amount' => 500,
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'status' => 'success',
            'jjb' => 500,
            'bank_jjb' => 500,
        ]);

        $this->assertDatabaseHas('users', [
            'id' => $user->id,
            'jjb' => 500,
            'bank_jjb' => 500,
        ]);

        $this->assertDatabaseHas('bank_logs', [
            'user_id' => $user->id,
            'type' => 'deposit',
            'amount' => 500,
            'balance_after' => 500,
        ]);
    }

    public function test_deposit_fails_if_insufficient_funds()
    {
        $user = User::factory()->create([
            'jjb' => 100,
            'bank_jjb' => 0,
        ]);

        $response = $this->actingAs($user)->postJson(route('bank.deposit'), [
            'amount' => 500,
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'status' => 'error',
        ]);

        $this->assertDatabaseMissing('bank_logs', [
            'user_id' => $user->id,
        ]);
    }

    public function test_withdraw_transfers_bank_to_jjb()
    {
        $user = User::factory()->create([
            'jjb' => 0,
            'bank_jjb' => 1000,
        ]);

        $response = $this->actingAs($user)->postJson(route('bank.withdraw'), [
            'amount' => 500,
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'status' => 'success',
            'jjb' => 500,
            'bank_jjb' => 500,
        ]);

        $this->assertDatabaseHas('bank_logs', [
            'user_id' => $user->id,
            'type' => 'withdraw',
            'amount' => 500,
            'balance_after' => 500,
        ]);
    }

    public function test_withdraw_fails_if_insufficient_funds()
    {
        $user = User::factory()->create([
            'jjb' => 0,
            'bank_jjb' => 100,
        ]);

        $response = $this->actingAs($user)->postJson(route('bank.withdraw'), [
            'amount' => 500,
        ]);

        $response->assertStatus(200);
        $response->assertJson([
            'status' => 'error',
        ]);
    }

    public function test_ranking_returns_paginated_users_ordered_by_bank_jjb()
    {
        $user = User::factory()->create(); // To act as

        User::factory()->create(['bank_jjb' => 1000, 'username' => 'Rich']);
        User::factory()->create(['bank_jjb' => 500, 'username' => 'Poorer']);

        $response = $this->actingAs($user)->getJson(route('bank.ranking'));

        $response->assertStatus(200);
        $response->assertJson([
            'status' => 'success',
        ]);

        $ranking = $response->json('ranking');
        $this->assertCount(2, $ranking);
        $this->assertEquals('Rich', $ranking[0]['username']);
        $this->assertEquals('Poorer', $ranking[1]['username']);
    }
}
