<?php

namespace Tests\Feature;

use App\Models\Account;
use App\Models\Currency;
use App\Models\Transaction;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class RequestedChangesTest extends TestCase
{
    use RefreshDatabase;

    public function test_buy_and_sell_affect_selected_non_lkr_account_by_rate_times_quantity(): void
    {
        $usd = Currency::create(['code' => 'USD', 'name' => 'US Dollar']);
        $eur = Currency::create(['code' => 'EUR', 'name' => 'Euro']);

        // Account used for LKR/USD payments
        $account = Account::create([
            'name' => 'USD Bank',
            'currency_id' => $usd->id,
            'type' => 'bank',
            'balance' => 10000,
        ]);

        // Account used for holding bought EUR
        $eurAccount = Account::create([
            'name' => 'EUR Cash',
            'currency_id' => $eur->id,
            'type' => 'cash',
            'balance' => 100,
        ]);

        // Define average cost basis for EUR by creating a buy transaction
        Transaction::create([
            'type' => 'buy',
            'currency_id' => $eur->id,
            'quantity' => 100,
            'rate' => 1.1,
            'payment_amount' => 110,
            'payment_currency_id' => $usd->id,
            'payment_account_id' => $account->id,
            'account_id' => $eurAccount->id,
        ]);

        // Reset account balance to 10,000 for test assertions
        $account->update(['balance' => 10000]);

        $this->withSession(['admin_logged_in' => true])
            ->post(route('transactions.buy.store'), [
                'currency_id' => $eur->id,
                'payment_account_id' => $account->id,
                'target_account_id' => $eurAccount->id,
                'quantity' => 10,
                'payment_amount' => 12, // 10 EUR bought at 1.2 rate
                'handling_fee' => 0,
            ]);

        $account->refresh();
        $this->assertEquals(9988.0000, (float) $account->balance);

        $this->withSession(['admin_logged_in' => true])
            ->post(route('transactions.sell.store'), [
                'currency_id' => $eur->id,
                'source_account_id' => $eurAccount->id,
                'target_account_id' => $account->id,
                'quantity' => 5,
                'payment_amount' => 7.5, // 5 EUR sold at 1.5 rate
                'handling_fee' => 0,
            ]);

        $account->refresh();
        $this->assertEquals(9995.5000, (float) $account->balance);
    }

    public function test_opening_balances_form_updates_account_balances(): void
    {
        $usd = Currency::create(['code' => 'USD', 'name' => 'US Dollar']);
        $account = Account::create([
            'name' => 'USD Cash',
            'currency_id' => $usd->id,
            'type' => 'cash',
            'balance' => 0,
        ]);

        $response = $this->withSession(['admin_logged_in' => true])
            ->post(route('setup.opening-balances.update'), [
                'balances' => [
                    $account->id => 25,
                ],
            ]);

        $response->assertRedirect(route('setup.opening-balances'));
        
        $account->refresh();
        $this->assertEquals(25.0000, (float) $account->balance);

        $this->assertDatabaseHas('transactions', [
            'type' => 'opening_balance',
            'currency_id' => $usd->id,
            'quantity' => 25,
            'account_id' => $account->id,
        ]);
    }

    public function test_accounts_currencies_can_be_edited_and_transaction_details_are_available(): void
    {
        $usd = Currency::create(['code' => 'USD', 'name' => 'US Dollar']);
        $lkr = Currency::create(['code' => 'LKR', 'name' => 'Sri Lankan Rupee']);

        $account = Account::create([
            'name' => 'Old Cash',
            'currency_id' => $lkr->id,
            'type' => 'cash',
            'balance' => 1000,
        ]);

        $transaction = Transaction::create([
            'type' => 'sell',
            'currency_id' => $usd->id,
            'quantity' => 3,
            'rate' => 330,
            'payment_amount' => 990,
            'payment_currency_id' => $lkr->id,
            'payment_account_id' => $account->id,
            'handling_fee' => 10,
            'fee_currency' => 'LKR',
            'account_id' => $account->id,
            'exchange_profit' => 90,
            'total_profit' => 90,
        ]);

        $this->withSession(['admin_logged_in' => true])
            ->put(route('currencies.update', $usd), [
                'code' => 'USDX',
                'name' => 'US Dollar Updated',
            ])
            ->assertRedirect(route('currencies.index'));

        $this->withSession(['admin_logged_in' => true])
            ->put(route('accounts.update', $account), [
                'name' => 'Updated Cash',
                'currency_id' => $lkr->id,
                'type' => 'bank',
            ])
            ->assertRedirect(route('accounts.index'));

        $this->withSession(['admin_logged_in' => true])
            ->get(route('reports.transactions.show', $transaction))
            ->assertOk()
            ->assertSee('USDX')
            ->assertSee('Updated Cash')
            ->assertSee('90.0000');
    }

    public function test_report_filters_support_ajax_and_excel_export(): void
    {
        $lkr = Currency::create(['code' => 'LKR', 'name' => 'Sri Lankan Rupee']);
        $usd = Currency::create(['code' => 'USD', 'name' => 'US Dollar']);

        $account = Account::create([
            'name' => 'Main Cash',
            'currency_id' => $lkr->id,
            'type' => 'cash',
            'balance' => 1000,
        ]);

        // Purchase USD to establish cost basis
        Transaction::create([
            'type' => 'buy',
            'currency_id' => $usd->id,
            'quantity' => 10,
            'rate' => 300,
            'payment_amount' => 3000,
            'payment_currency_id' => $lkr->id,
            'payment_account_id' => $account->id,
            'account_id' => $account->id,
        ]);

        Transaction::create([
            'type' => 'sell',
            'currency_id' => $usd->id,
            'quantity' => 2,
            'rate' => 330,
            'payment_amount' => 660,
            'handling_fee' => 10,
            'fee_currency' => 'LKR',
            'account_id' => $account->id,
            'payment_currency_id' => $lkr->id,
            'payment_account_id' => $account->id,
            'exchange_profit' => 60,
            'total_profit' => 60,
        ]);

        $this->withSession(['admin_logged_in' => true])
            ->get(route('reports.profits', ['currency_id' => $usd->id]), ['X-Requested-With' => 'XMLHttpRequest'])
            ->assertOk()
            ->assertSee('USD')
            ->assertSee('60.0000');

        $this->withSession(['admin_logged_in' => true])
            ->get(route('reports.handling-fees'), ['X-Requested-With' => 'XMLHttpRequest'])
            ->assertOk()
            ->assertSee('10.0000')
            ->assertSee('LKR');

        $this->withSession(['admin_logged_in' => true])
            ->get(route('reports.transactions', ['export' => 'xls']))
            ->assertOk()
            ->assertHeader('Content-Type', 'application/vnd.ms-excel');
    }
}
