<?php

namespace Tests\Feature\BranchIsolation;

use App\Models\Branch;
use App\Models\Business;
use App\Models\Customer;
use App\Models\FinancialAccount;
use App\Models\FixedAsset;
use App\Models\FixedAssetMaintenance;
use App\Models\Loan;
use App\Models\LoanPayment;
use App\Models\LoanProduct;
use App\Models\RemotePaymentSubmission;
use App\Models\Role;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class FixedAssetRemotePaymentIntegrityTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        $this->seed(DatabaseSeeder::class);
    }

    public function test_multi_branch_accountant_cannot_mix_accounts_across_fixed_assets_or_remote_payments(): void
    {
        [$branchA, $branchB, $accountA, $accountB, $actor] = $this->branchFixture();
        $balanceA = $accountA->current_balance;
        $balanceB = $accountB->current_balance;

        $this->actingAs($actor)
            ->from(route('fixed-assets.create'))
            ->post(route('fixed-assets.store'), [
                'branch_id' => $branchA->id,
                'name' => 'Cross Branch Laptop',
                'category' => 'Computer Equipment',
                'acquisition_source' => 'financial_account',
                'acquisition_date' => '2026-08-13',
                'acquisition_cost' => '1000.00',
                'residual_value' => '0.00',
                'depreciation_method' => 'straight_line',
                'useful_life_months' => 12,
                'financial_account_id' => $accountB->id,
                'status' => 'active',
            ])
            ->assertRedirect(route('fixed-assets.create'))
            ->assertSessionHasErrors('financial_account_id');

        $this->assertSame(0, FixedAsset::count());
        $this->assertSame($balanceA, $accountA->fresh()->current_balance);
        $this->assertSame($balanceB, $accountB->fresh()->current_balance);

        $asset = FixedAsset::create([
            'business_id' => $branchA->business_id,
            'branch_id' => $branchA->id,
            'asset_number' => 'AST-INTEGRITY-A',
            'name' => 'Integrity Desk',
            'category' => 'Furniture',
            'acquisition_source' => 'opening',
            'acquisition_date' => '2026-08-01',
            'depreciation_start_date' => '2026-08-01',
            'acquisition_cost' => '500.00',
            'residual_value' => '0.00',
            'depreciation_method' => 'straight_line',
            'useful_life_months' => 12,
            'accumulated_depreciation' => '0.00',
            'book_value' => '500.00',
            'status' => 'active',
            'created_by' => $actor->id,
            'updated_by' => $actor->id,
        ]);

        $this->actingAs($actor)
            ->from(route('fixed-assets.show', $asset))
            ->post(route('fixed-assets.maintenance', $asset), [
                'maintenance_date' => '2026-08-13',
                'maintenance_type' => 'service',
                'description' => 'Cross-branch maintenance attempt',
                'cost' => '50.00',
                'financial_account_id' => $accountB->id,
            ])
            ->assertRedirect(route('fixed-assets.show', $asset))
            ->assertSessionHasErrors('financial_account_id');

        $this->assertSame(0, FixedAssetMaintenance::count());
        $this->assertSame($balanceA, $accountA->fresh()->current_balance);
        $this->assertSame($balanceB, $accountB->fresh()->current_balance);

        [$loan, $submission] = $this->remotePaymentFixture($branchA, $actor);

        $this->actingAs($actor)
            ->from(route('remote-payments.show', $submission))
            ->post(route('remote-payments.approve', $submission), [
                'financial_account_id' => $accountB->id,
                'payment_date' => '2026-08-13',
                'verification_notes' => 'Crafted cross-branch account selection.',
            ])
            ->assertRedirect(route('remote-payments.show', $submission))
            ->assertSessionHasErrors('financial_account_id');

        $this->assertSame('pending_verification', $submission->fresh()->status);
        $this->assertNull($submission->fresh()->loan_payment_id);
        $this->assertSame(0, LoanPayment::where('loan_id', $loan->id)->count());
        $this->assertSame($balanceA, $accountA->fresh()->current_balance);
        $this->assertSame($balanceB, $accountB->fresh()->current_balance);
    }

    private function branchFixture(): array
    {
        $business = Business::firstOrFail();
        $branchA = Branch::create(['business_id' => $business->id, 'name' => 'Integrity Assets A', 'status' => 'active']);
        $branchB = Branch::create(['business_id' => $business->id, 'name' => 'Integrity Assets B', 'status' => 'active']);
        $accountA = FinancialAccount::create([
            'branch_id' => $branchA->id,
            'name' => 'Integrity Asset Cash A',
            'account_type' => 'cash',
            'opening_balance' => '10000.00',
            'current_balance' => '10000.00',
            'status' => 'active',
        ]);
        $accountB = FinancialAccount::create([
            'branch_id' => $branchB->id,
            'name' => 'Integrity Asset Cash B',
            'account_type' => 'cash',
            'opening_balance' => '10000.00',
            'current_balance' => '10000.00',
            'status' => 'active',
        ]);
        $actor = User::factory()->create([
            'name' => 'Multi Branch Integrity Accountant',
            'username' => 'multi_branch_asset_integrity',
            'status' => 'active',
            'primary_branch_id' => $branchA->id,
        ]);
        $actor->roles()->attach(Role::where('name', 'accountant')->firstOrFail());
        $actor->branches()->attach($branchA->id, ['is_primary' => true]);
        $actor->branches()->attach($branchB->id, ['is_primary' => false]);

        return [$branchA, $branchB, $accountA, $accountB, $actor];
    }

    private function remotePaymentFixture(Branch $branch, User $actor): array
    {
        $business = $branch->business;
        $customer = Customer::create([
            'branch_id' => $branch->id,
            'customer_number' => 'CUS-RMP-INTEGRITY',
            'identity_mode' => 'without_nin',
            'first_name' => 'Asha',
            'last_name' => 'Musa',
            'phone' => '0755009911',
            'status' => 'active',
        ]);
        $product = LoanProduct::create([
            'business_id' => $business->id,
            'name' => 'Remote Integrity Product',
            'minimum_amount' => '10000.00',
            'maximum_amount' => '500000.00',
            'duration' => 2,
            'duration_unit' => 'months',
            'interest_rate' => '10.000000',
            'interest_calculation_method' => 'flat',
            'repayment_frequency' => 'monthly',
            'grace_period_days' => 0,
            'late_payment_penalty_type' => 'fixed',
            'late_payment_penalty_value' => '0.000000',
            'processing_fee_type' => 'fixed',
            'processing_fee_value' => '0.000000',
            'insurance_fee_type' => 'fixed',
            'insurance_fee_value' => '0.000000',
            'other_charges' => '0.00',
            'collateral_required' => false,
            'guarantor_required' => false,
            'status' => 'active',
        ]);
        $loan = Loan::create([
            'branch_id' => $branch->id,
            'customer_id' => $customer->id,
            'loan_product_id' => $product->id,
            'sequence_number' => 1,
            'sequence_year' => 2026,
            'loan_number' => 'LN-RMP-INTEGRITY',
            'principal' => '100000.00',
            'interest' => '10000.00',
            'processing_fee' => '0.00',
            'insurance_fee' => '0.00',
            'other_charges' => '0.00',
            'fees' => '0.00',
            'total_repayment' => '110000.00',
            'principal_outstanding' => '100000.00',
            'interest_outstanding' => '10000.00',
            'fees_outstanding' => '0.00',
            'penalties_outstanding' => '0.00',
            'total_outstanding' => '110000.00',
            'total_paid' => '0.00',
            'purpose' => 'Integrity validation',
            'schedule_start_date' => '2026-08-13',
            'status' => 'active',
            'disbursed_at' => now(),
            'activated_at' => now(),
            'schedule_activated_at' => now(),
        ]);
        $submission = RemotePaymentSubmission::create([
            'submission_number' => 'RMP-INTEGRITY-2026-000001',
            'loan_id' => $loan->id,
            'customer_id' => $customer->id,
            'branch_id' => $branch->id,
            'amount' => '1000.00',
            'payment_channel' => 'mpesa',
            'transaction_reference' => 'RMP-INTEGRITY-REF',
            'proof_path' => 'remote-payments/integrity/proof.pdf',
            'proof_original_name' => 'proof.pdf',
            'proof_mime_type' => 'application/pdf',
            'proof_file_size' => 100,
            'status' => 'pending_verification',
            'submitted_by_type' => 'staff',
            'submitted_by_user_id' => $actor->id,
            'submitted_at' => now(),
            'provider_code' => 'manual-review',
            'provider_status' => 'manual_review_required',
        ]);

        return [$loan, $submission];
    }
}
