<?php

namespace Tests\Feature\BranchIsolation;

use App\Models\Branch;
use App\Models\Business;
use App\Models\Customer;
use App\Models\ExpenseCategory;
use App\Models\FinancialAccount;
use App\Models\Loan;
use App\Models\LoanProduct;
use App\Models\PayrollPeriod;
use App\Models\Permission;
use App\Models\RecurringExpense;
use App\Models\ReminderNotificationLog;
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 Phase8OperationalControllerScopeTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_primary_only_user_keeps_operational_scope_without_branch_pivot(): void
    {
        $business = Business::firstOrFail();
        $branchA = Branch::create(['business_id'=>$business->id,'name'=>'Phase 8 Ops A','status'=>'active']);
        $branchB = Branch::create(['business_id'=>$business->id,'name'=>'Phase 8 Ops B','status'=>'active']);

        $role = Role::create(['name'=>'phase8-operations','display_name'=>'Phase 8 Operations']);
        $role->permissions()->attach(Permission::whereIn('name', [
            'notifications.view',
            'payments.remote.submit',
            'expenses.view',
            'expenses.recurring.manage',
            'payroll.view',
            'payroll.compensation.manage',
            'payroll.periods.create',
        ])->pluck('id'));

        $user = User::factory()->create([
            'username'=>'phase8_ops_primary_only',
            'status'=>'active',
            'primary_branch_id'=>$branchA->id,
        ]);
        $user->roles()->attach($role->id);
        $this->assertSame([], $user->branches()->pluck('branches.id')->all());

        $product = $this->product($business);
        $customerA = Customer::factory()->create(['branch_id'=>$branchA->id,'customer_number'=>'CUS-P8-OPS-A']);
        $customerB = Customer::factory()->create(['branch_id'=>$branchB->id,'customer_number'=>'CUS-P8-OPS-B']);
        $loanA = $this->loan($branchA,$customerA,$product,'LN-P8-OPS-A',1);
        $loanB = $this->loan($branchB,$customerB,$product,'LN-P8-OPS-B',2);
        $installmentA = $loanA->installments()->create($this->installment(1));
        $installmentB = $loanB->installments()->create($this->installment(1));

        ReminderNotificationLog::create([
            'business_id'=>$business->id,'branch_id'=>$branchA->id,'customer_id'=>$customerA->id,'loan_id'=>$loanA->id,
            'loan_installment_id'=>$installmentA->id,'reminder_type'=>'due','days_from_due'=>0,'channel'=>'sms',
            'recipient'=>'255700000001','message'=>'Phase 8 primary reminder','scheduled_for'=>'2026-08-13','status'=>'pending','idempotency_key'=>str_repeat('a',64),
        ]);
        ReminderNotificationLog::create([
            'business_id'=>$business->id,'branch_id'=>$branchB->id,'customer_id'=>$customerB->id,'loan_id'=>$loanB->id,
            'loan_installment_id'=>$installmentB->id,'reminder_type'=>'due','days_from_due'=>0,'channel'=>'sms',
            'recipient'=>'255700000002','message'=>'Phase 8 other reminder','scheduled_for'=>'2026-08-13','status'=>'pending','idempotency_key'=>str_repeat('b',64),
        ]);

        RemotePaymentSubmission::create([
            'submission_number'=>'RPS-P8-OPS-A','loan_id'=>$loanA->id,'customer_id'=>$customerA->id,'branch_id'=>$branchA->id,
            'amount'=>'1000.00','payment_channel'=>'mpesa','transaction_reference'=>'P8-OPS-A','proof_path'=>'remote/a.jpg',
            'proof_original_name'=>'a.jpg','status'=>'pending_verification','submitted_by_type'=>'staff','submitted_by_user_id'=>$user->id,'submitted_at'=>now(),
        ]);
        RemotePaymentSubmission::create([
            'submission_number'=>'RPS-P8-OPS-B','loan_id'=>$loanB->id,'customer_id'=>$customerB->id,'branch_id'=>$branchB->id,
            'amount'=>'1000.00','payment_channel'=>'mpesa','transaction_reference'=>'P8-OPS-B','proof_path'=>'remote/b.jpg',
            'proof_original_name'=>'b.jpg','status'=>'pending_verification','submitted_by_type'=>'staff','submitted_by_user_id'=>$user->id,'submitted_at'=>now(),
        ]);

        $category = ExpenseCategory::where('business_id',$business->id)->firstOrFail();
        $accountA = FinancialAccount::create([
            'branch_id'=>$branchA->id,'name'=>'Phase 8 Ops Cash A','account_type'=>'cash','opening_balance'=>'100000.00','current_balance'=>'100000.00','status'=>'active',
        ]);
        $accountB = FinancialAccount::create([
            'branch_id'=>$branchB->id,'name'=>'Phase 8 Ops Cash B','account_type'=>'cash','opening_balance'=>'100000.00','current_balance'=>'100000.00','status'=>'active',
        ]);
        $this->recurringExpense($business,$branchA,$category,$accountA,$user,'Phase 8 recurring A');
        $this->recurringExpense($business,$branchB,$category,$accountB,$user,'Phase 8 recurring B');
        $this->payrollPeriod($business,$branchA,$user,'PAY-P8-OPS-A','Phase 8 payroll A');
        $this->payrollPeriod($business,$branchB,$user,'PAY-P8-OPS-B','Phase 8 payroll B');

        $this->actingAs($user)->get(route('notifications.index'))
            ->assertOk()->assertSee('Phase 8 primary reminder')->assertDontSee('Phase 8 other reminder');

        $this->actingAs($user)->get(route('remote-payments.index'))
            ->assertOk()->assertSee('RPS-P8-OPS-A')->assertDontSee('RPS-P8-OPS-B');

        $this->actingAs($user)->get(route('recurring-expenses.index'))
            ->assertOk()->assertSee('Phase 8 recurring A')->assertDontSee('Phase 8 recurring B');

        $this->actingAs($user)->get(route('recurring-expenses.create'))
            ->assertOk()->assertSee($branchA->name)->assertSee($accountA->name)->assertDontSee($branchB->name)->assertDontSee($accountB->name);

        $this->actingAs($user)->get(route('payroll.index'))
            ->assertOk()->assertSee('PAY-P8-OPS-A')->assertDontSee('PAY-P8-OPS-B');

        $this->actingAs($user)->get(route('payroll.create'))
            ->assertOk()->assertSee($branchA->name)->assertDontSee($branchB->name);
    }

    private function product(Business $business): LoanProduct
    {
        return LoanProduct::create([
            'business_id'=>$business->id,'name'=>'Phase 8 Ops Product','minimum_amount'=>'1000.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'=>'none','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',
        ]);
    }

    private function loan(Branch $branch, Customer $customer, LoanProduct $product, string $number, int $sequence): Loan
    {
        return Loan::create([
            'branch_id'=>$branch->id,'customer_id'=>$customer->id,'loan_product_id'=>$product->id,'sequence_number'=>$sequence,
            'sequence_year'=>2026,'loan_number'=>$number,'principal'=>'10000.00','interest'=>'1000.00','processing_fee'=>'0.00',
            'insurance_fee'=>'0.00','other_charges'=>'0.00','fees'=>'0.00','total_repayment'=>'11000.00','principal_outstanding'=>'10000.00',
            'interest_outstanding'=>'1000.00','fees_outstanding'=>'0.00','penalties_outstanding'=>'0.00','total_outstanding'=>'11000.00','total_paid'=>'0.00',
            'purpose'=>'Phase 8 operational scope','schedule_start_date'=>'2026-08-01','status'=>'active','disbursed_at'=>now(),'activated_at'=>now(),
            'schedule_activated_at'=>now(),
        ]);
    }

    private function installment(int $number): array
    {
        return [
            'installment_number'=>$number,'principal'=>'10000.00','interest'=>'1000.00','fees'=>'0.00','amount_due'=>'11000.00',
            'due_date'=>'2026-08-13','amount_paid'=>'0.00','remaining'=>'11000.00','status'=>'pending','principal_paid'=>'0.00',
            'interest_paid'=>'0.00','fees_paid'=>'0.00','penalty_due'=>'0.00','penalty_paid'=>'0.00',
        ];
    }

    private function recurringExpense(Business $business, Branch $branch, ExpenseCategory $category, FinancialAccount $account, User $user, string $description): void
    {
        RecurringExpense::create([
            'business_id'=>$business->id,'branch_id'=>$branch->id,'expense_category_id'=>$category->id,'financial_account_id'=>$account->id,
            'description'=>$description,'amount'=>'5000.00','start_date'=>'2026-08-01','next_due_date'=>'2026-08-20','recurrence'=>'monthly',
            'reminder_days_before'=>3,'status'=>'active','created_by'=>$user->id,'updated_by'=>$user->id,
        ]);
    }

    private function payrollPeriod(Business $business, Branch $branch, User $user, string $number, string $name): void
    {
        PayrollPeriod::create([
            'period_number'=>$number,'business_id'=>$business->id,'branch_id'=>$branch->id,'name'=>$name,'start_date'=>'2026-08-01',
            'end_date'=>'2026-08-31','pay_date'=>'2026-08-31','status'=>'draft','created_by'=>$user->id,
        ]);
    }
}
