<?php

use App\Enums\AccountStatus;
use App\Enums\AccountType;
use App\Enums\Currency;
use App\Enums\PaymentMethodType;
use App\Enums\RequestStatus;
use App\Enums\UserStatus;
use App\Enums\UserType;
use App\Models\Account;
use App\Models\AppSetting;
use App\Models\PaymentMethod;
use App\Models\User;

function createActiveUser(): User
{
    AppSetting::set('otp_enabled', 'false');
    AppSetting::set('maintenance_mode', 'false');

    $user = User::factory()->create([
        'status' => UserStatus::Active,
        'type' => UserType::User,
        'password' => 'password',
    ]);

    Account::create([
        'user_id' => $user->id,
        'account_number' => Account::generateAccountNumber(),
        'account_type' => AccountType::Checking,
        'currency' => Currency::USD,
        'balance' => 10000.00,
        'status' => AccountStatus::Active,
    ]);

    return $user;
}

// Dashboard Tests
test('dashboard page renders for active user', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/dashboard')
        ->assertOk();
});

test('dashboard requires authentication', function () {
    $this->get('/dashboard')->assertRedirect('/login');
});

test('pending user cannot access dashboard', function () {
    AppSetting::set('otp_enabled', 'false');
    $user = User::factory()->create([
        'status' => UserStatus::Pending,
        'type' => UserType::User,
    ]);

    $this->actingAs($user)
        ->get('/dashboard')
        ->assertRedirect(route('pending'));
});

// Accounts Tests
test('accounts page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/accounts')
        ->assertOk();
});

// Transactions Tests
test('transactions page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/transactions')
        ->assertOk();
});

// Transfer Tests
test('transfer page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/transfer')
        ->assertOk();
});

test('internal transfer works with valid data', function () {
    $sender = createActiveUser();
    $senderAccount = $sender->accounts->first();

    $recipient = createActiveUser();
    $recipientAccount = $recipient->accounts->first();

    $this->actingAs($sender)
        ->post('/transfer/internal', [
            'from_account_id' => $senderAccount->id,
            'to_identifier' => $recipientAccount->account_number,
            'amount' => 100.00,
            'description' => 'Test transfer',
            'password' => 'password',
        ])
        ->assertRedirect(route('transfer'))
        ->assertSessionHas('success');

    expect((float) $senderAccount->fresh()->balance)->toBe(9900.00);
    expect((float) $recipientAccount->fresh()->balance)->toBe(10100.00);
});

test('internal transfer fails with insufficient balance', function () {
    $sender = createActiveUser();
    $senderAccount = $sender->accounts->first();

    $recipient = createActiveUser();
    $recipientAccount = $recipient->accounts->first();

    $this->actingAs($sender)
        ->post('/transfer/internal', [
            'from_account_id' => $senderAccount->id,
            'to_identifier' => $recipientAccount->account_number,
            'amount' => 99999.00,
            'description' => 'Too much',
            'password' => 'password',
        ])
        ->assertSessionHasErrors('amount');
});

test('internal transfer fails with wrong password', function () {
    $sender = createActiveUser();
    $senderAccount = $sender->accounts->first();

    $recipient = createActiveUser();
    $recipientAccount = $recipient->accounts->first();

    $this->actingAs($sender)
        ->post('/transfer/internal', [
            'from_account_id' => $senderAccount->id,
            'to_identifier' => $recipientAccount->account_number,
            'amount' => 100.00,
            'description' => 'Test',
            'password' => 'wrongpass',
        ])
        ->assertSessionHasErrors('password');
});

// Deposit Tests
test('deposit page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/deposit')
        ->assertOk();
});

test('deposit request can be submitted', function () {
    $user = createActiveUser();
    $account = $user->accounts->first();

    $pm = PaymentMethod::create([
        'name' => 'Test Bank Transfer',
        'type' => PaymentMethodType::BankTransfer,
        'instructions' => 'Send to account 12345',
        'is_active' => true,
    ]);

    $this->actingAs($user)
        ->post('/deposit', [
            'account_id' => $account->id,
            'payment_method_id' => $pm->id,
            'amount' => 500.00,
            'proof' => \Illuminate\Http\UploadedFile::fake()->image('receipt.jpg'),
        ])
        ->assertRedirect(route('deposit'))
        ->assertSessionHas('success');

    $this->assertDatabaseHas('deposit_requests', [
        'user_id' => $user->id,
        'account_id' => $account->id,
        'amount' => 500.00,
        'status' => RequestStatus::Pending->value,
    ]);
});

// Withdraw Tests
test('withdraw page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/withdraw')
        ->assertOk();
});

test('withdrawal request can be submitted', function () {
    $user = createActiveUser();
    $account = $user->accounts->first();

    $this->actingAs($user)
        ->post('/withdraw', [
            'account_id' => $account->id,
            'amount' => 200.00,
            'bank_name' => 'Chase Bank',
            'account_number' => '123456789',
            'routing_number' => '021000021',
            'description' => 'Monthly withdrawal',
            'password' => 'password',
        ])
        ->assertRedirect(route('withdraw'))
        ->assertSessionHas('success');

    $this->assertDatabaseHas('withdrawal_requests', [
        'user_id' => $user->id,
        'account_id' => $account->id,
        'amount' => 200.00,
        'status' => RequestStatus::Pending->value,
    ]);
});

// Brokerage Tests
test('brokerage page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/brokerage')
        ->assertOk();
});

// Notifications Tests
test('notifications page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/notifications')
        ->assertOk();
});

// Profile Tests
test('profile page renders', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->get('/profile')
        ->assertOk();
});

test('user can update profile', function () {
    $user = createActiveUser();

    $this->actingAs($user)
        ->post('/profile', [
            'first_name' => 'Updated',
            'last_name' => 'Name',
            'phone' => '+19876543210',
            'address' => '456 New St',
            'country' => 'US',
        ])
        ->assertRedirect(route('profile'));

    expect($user->fresh()->first_name)->toBe('Updated');
});
