<?php

namespace Tests\Feature\BranchIsolation;

use App\Models\Branch;
use App\Models\Business;
use App\Models\Customer;
use App\Models\CustomerAddress;
use App\Models\CustomerRiskProfile;
use App\Models\FinancialAccount;
use App\Models\Guarantor;
use App\Models\Loan;
use App\Models\LoanInstallment;
use App\Models\LoanPayment;
use App\Models\LoanPaymentAllocation;
use App\Models\LoanProduct;
use App\Models\NextOfKin;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class RemainingParentOwnedScopeTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_remaining_parent_owned_records_follow_their_parent_branch_scope(): void
    {
        $business = Business::firstOrFail();
        $branchA = Branch::factory()->create(['business_id' => $business->id, 'name' => 'Phase 4 Remaining A']);
        $branchB = Branch::factory()->create(['business_id' => $business->id, 'name' => 'Phase 4 Remaining B']);

        $customerA = Customer::factory()->create(['branch_id' => $branchA->id]);
        $customerB = Customer::factory()->create(['branch_id' => $branchB->id]);
        $product = LoanProduct::factory()->create(['business_id' => $business->id]);
        $loanA = $this->loan($branchA, $customerA, $product, 'LON-P4-REM-A');
        $loanB = $this->loan($branchB, $customerB, $product, 'LON-P4-REM-B');

        CustomerAddress::create(['customer_id' => $customerA->id, 'region' => 'Region A']);
        CustomerAddress::create(['customer_id' => $customerB->id, 'region' => 'Region B']);
        NextOfKin::create(['customer_id' => $customerA->id, 'full_name' => 'Kin A', 'relationship' => 'Sibling']);
        NextOfKin::create(['customer_id' => $customerB->id, 'full_name' => 'Kin B', 'relationship' => 'Sibling']);
        Guarantor::create(['customer_id' => $customerA->id, 'full_name' => 'Guarantor A', 'phone' => '0712345678', 'status' => 'active']);
        Guarantor::create(['customer_id' => $customerB->id, 'full_name' => 'Guarantor B', 'phone' => '0712345679', 'status' => 'active']);
        CustomerRiskProfile::create(['customer_id' => $customerA->id, 'risk_level' => 'low', 'score' => '10.00']);
        CustomerRiskProfile::create(['customer_id' => $customerB->id, 'risk_level' => 'high', 'score' => '90.00']);

        $installmentA = $this->installment($loanA, 1);
        $installmentB = $this->installment($loanB, 1);
        $accountA = FinancialAccount::create(['branch_id' => $branchA->id, 'name' => 'Phase 4 Cash A', 'account_type' => 'cash', 'status' => 'active']);
        $accountB = FinancialAccount::create(['branch_id' => $branchB->id, 'name' => 'Phase 4 Cash B', 'account_type' => 'cash', 'status' => 'active']);
        $paymentA = $this->payment($loanA, $customerA, $branchA, $accountA, 'REC-P4-REM-A');
        $paymentB = $this->payment($loanB, $customerB, $branchB, $accountB, 'REC-P4-REM-B');
        LoanPaymentAllocation::create(['loan_payment_id' => $paymentA->id, 'loan_installment_id' => $installmentA->id, 'principal' => '100.00', 'total' => '100.00']);
        LoanPaymentAllocation::create(['loan_payment_id' => $paymentB->id, 'loan_installment_id' => $installmentB->id, 'principal' => '100.00', 'total' => '100.00']);

        $branchAUser = User::factory()->create(['primary_branch_id' => $branchA->id]);
        $branchAUser->branches()->attach($branchA->id, ['is_primary' => true]);
        $this->actingAs($branchAUser);
        $this->assertSame(['Region A'], CustomerAddress::pluck('region')->all());
        $this->assertSame(['Kin A'], NextOfKin::pluck('full_name')->all());
        $this->assertSame(['Guarantor A'], Guarantor::pluck('full_name')->all());
        $this->assertSame(['low'], CustomerRiskProfile::pluck('risk_level')->all());
        $this->assertSame([$loanA->id], LoanInstallment::pluck('loan_id')->all());
        $this->assertSame([$paymentA->id], LoanPaymentAllocation::pluck('loan_payment_id')->all());

        $multiBranchUser = User::factory()->create(['primary_branch_id' => $branchA->id]);
        $multiBranchUser->branches()->attach([
            $branchA->id => ['is_primary' => true],
            $branchB->id => ['is_primary' => false],
        ]);
        $this->actingAs($multiBranchUser);
        $this->assertSame(2, CustomerAddress::count());
        $this->assertSame(2, NextOfKin::count());
        $this->assertSame(2, Guarantor::count());
        $this->assertSame(2, CustomerRiskProfile::count());
        $this->assertSame(2, LoanInstallment::count());
        $this->assertSame(2, LoanPaymentAllocation::count());

        $noBranchUser = User::factory()->create(['primary_branch_id' => null]);
        $this->actingAs($noBranchUser);
        $this->assertSame(0, CustomerAddress::count());
        $this->assertSame(0, NextOfKin::count());
        $this->assertSame(0, Guarantor::count());
        $this->assertSame(0, CustomerRiskProfile::count());
        $this->assertSame(0, LoanInstallment::count());
        $this->assertSame(0, LoanPaymentAllocation::count());

        $superAdmin = User::where('email', 'admin@microfinance.local')->firstOrFail();
        $this->actingAs($superAdmin);
        $this->assertSame(2, CustomerAddress::count());
        $this->assertSame(2, NextOfKin::count());
        $this->assertSame(2, Guarantor::count());
        $this->assertSame(2, CustomerRiskProfile::count());
        $this->assertSame(2, LoanInstallment::count());
        $this->assertSame(2, LoanPaymentAllocation::count());
    }

    private function loan(Branch $branch, Customer $customer, LoanProduct $product, string $number): Loan
    {
        return Loan::create([
            'branch_id' => $branch->id,
            'customer_id' => $customer->id,
            'loan_product_id' => $product->id,
            'sequence_number' => $branch->id,
            'sequence_year' => 2026,
            'loan_number' => $number,
            'principal' => '1000.00',
            'interest' => '100.00',
            'processing_fee' => '0.00',
            'insurance_fee' => '0.00',
            'other_charges' => '0.00',
            'fees' => '0.00',
            'total_repayment' => '1100.00',
            'purpose' => 'Remaining parent scope test',
            'schedule_start_date' => '2026-08-14',
            'status' => 'active',
            'principal_outstanding' => '1000.00',
            'interest_outstanding' => '100.00',
            'fees_outstanding' => '0.00',
            'penalties_outstanding' => '0.00',
            'total_outstanding' => '1100.00',
        ]);
    }

    private function installment(Loan $loan, int $number): LoanInstallment
    {
        return LoanInstallment::create([
            'loan_id' => $loan->id,
            'installment_number' => $number,
            'principal' => '500.00',
            'interest' => '50.00',
            'fees' => '0.00',
            'amount_due' => '550.00',
            'due_date' => '2026-09-14',
            'amount_paid' => '0.00',
            'remaining' => '550.00',
            'status' => 'upcoming',
        ]);
    }

    private function payment(Loan $loan, Customer $customer, Branch $branch, FinancialAccount $account, string $receipt): LoanPayment
    {
        return LoanPayment::create([
            'receipt_number' => $receipt,
            'loan_id' => $loan->id,
            'customer_id' => $customer->id,
            'branch_id' => $branch->id,
            'financial_account_id' => $account->id,
            'amount' => '100.00',
            'principal_amount' => '100.00',
            'payment_date' => '2026-08-14 12:00:00',
            'method' => 'cash',
        ]);
    }
}
