<?php

namespace Tests\Feature\BranchIsolation;

use App\Models\Branch;
use App\Models\Business;
use App\Models\Customer;
use App\Models\Expense;
use App\Models\ExpenseCategory;
use App\Models\FinancialAccount;
use App\Models\Loan;
use App\Models\LoanDisbursement;
use App\Models\LoanPayment;
use App\Models\LoanProduct;
use App\Models\Role;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CrossBranchIntegrityValidationTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_multi_branch_user_cannot_mix_financial_accounts_across_branch_owned_writes(): void
    {
        [$branchA,$branchB,$loan,$accountA,$accountB,$category,$actor] = $this->fixture();
        $accountABalance = $accountA->current_balance;
        $accountBBalance = $accountB->current_balance;

        $this->actingAs($actor)
            ->from(route('loan-payments.create',$loan))
            ->post(route('loan-payments.store',$loan),[
                'amount'=>'1000.00',
                'date'=>'2026-08-13',
                'method'=>'cash',
                'financial_account_id'=>$accountB->id,
            ])
            ->assertRedirect(route('loan-payments.create',$loan))
            ->assertSessionHasErrors('financial_account_id');

        $this->actingAs($actor)
            ->from(route('loan-disbursements.create',$loan))
            ->post(route('loan-disbursements.store',$loan),[
                'amount'=>'500000.00',
                'financial_account_id'=>$accountB->id,
                'date'=>'2026-08-13',
            ])
            ->assertRedirect(route('loan-disbursements.create',$loan))
            ->assertSessionHasErrors('financial_account_id');

        $this->actingAs($actor)
            ->from(route('loan-disbursements.create',$loan))
            ->post(route('loan-disbursements.store',$loan),[
                'amount'=>'500000.00',
                'financial_account_id'=>$accountA->id,
                'processing_fee_account_id'=>$accountB->id,
                'date'=>'2026-08-13',
            ])
            ->assertRedirect(route('loan-disbursements.create',$loan))
            ->assertSessionHasErrors('processing_fee_account_id');

        $this->actingAs($actor)
            ->from(route('expenses.create'))
            ->post(route('expenses.store'),[
                'branch_id'=>$branchA->id,
                'expense_category_id'=>$category->id,
                'financial_account_id'=>$accountB->id,
                'description'=>'Cross-branch crafted expense',
                'amount'=>'5000.00',
                'expense_date'=>'2026-08-13',
            ])
            ->assertRedirect(route('expenses.create'))
            ->assertSessionHasErrors('financial_account_id');

        $this->assertSame(0,LoanPayment::count());
        $this->assertSame(0,LoanDisbursement::count());
        $this->assertSame(0,Expense::count());
        $this->assertSame($accountABalance,$accountA->fresh()->current_balance);
        $this->assertSame($accountBBalance,$accountB->fresh()->current_balance);
    }

    private function fixture(): array
    {
        $business=Business::firstOrFail();
        $business->update(['require_signed_contract_before_disbursement'=>false]);
        $branchA=Branch::create(['business_id'=>$business->id,'name'=>'Integrity Branch A','status'=>'active']);
        $branchB=Branch::create(['business_id'=>$business->id,'name'=>'Integrity Branch B','status'=>'active']);
        $customer=Customer::create([
            'branch_id'=>$branchA->id,
            'customer_number'=>'CUS-INTEGRITY-A',
            'identity_mode'=>'without_nin',
            'first_name'=>'Amina',
            'last_name'=>'Juma',
            'phone'=>'0755007001',
            'status'=>'active',
        ]);
        $product=LoanProduct::create([
            'business_id'=>$business->id,
            'name'=>'Integrity Product',
            'minimum_amount'=>'100000.00',
            'maximum_amount'=>'1000000.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'=>$branchA->id,
            'customer_id'=>$customer->id,
            'loan_product_id'=>$product->id,
            'sequence_number'=>1,
            'sequence_year'=>2026,
            'loan_number'=>'LN-INTEGRITY-A',
            'principal'=>'500000.00',
            'interest'=>'50000.00',
            'processing_fee'=>'0.00',
            'insurance_fee'=>'0.00',
            'other_charges'=>'0.00',
            'fees'=>'0.00',
            'total_repayment'=>'550000.00',
            'principal_outstanding'=>'500000.00',
            'interest_outstanding'=>'50000.00',
            'fees_outstanding'=>'0.00',
            'penalties_outstanding'=>'0.00',
            'total_outstanding'=>'550000.00',
            'total_paid'=>'0.00',
            'purpose'=>'Integrity validation',
            'schedule_start_date'=>'2026-09-13',
            'status'=>'ready_for_disbursement',
            'approved_at'=>now(),
        ]);
        $accountA=FinancialAccount::create([
            'branch_id'=>$branchA->id,
            'name'=>'Integrity Cash A',
            'account_type'=>'cash',
            'opening_balance'=>'1000000.00',
            'current_balance'=>'1000000.00',
            'status'=>'active',
        ]);
        $accountB=FinancialAccount::create([
            'branch_id'=>$branchB->id,
            'name'=>'Integrity Cash B',
            'account_type'=>'cash',
            'opening_balance'=>'1000000.00',
            'current_balance'=>'1000000.00',
            'status'=>'active',
        ]);
        $category=ExpenseCategory::where('business_id',$business->id)->where('name','Rent')->firstOrFail();
        $actor=User::factory()->create([
            'name'=>'Multi Branch Integrity User',
            'username'=>'multi_branch_integrity',
            'status'=>'active',
            'primary_branch_id'=>$branchA->id,
        ]);
        $actor->roles()->attach([
            Role::where('name','cashier')->firstOrFail()->id,
            Role::where('name','accountant')->firstOrFail()->id,
        ]);
        $actor->branches()->attach($branchA->id,['is_primary'=>true]);
        $actor->branches()->attach($branchB->id,['is_primary'=>false]);

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