<?php

namespace Tests\Feature;

use App\Models\Branch;
use App\Models\Business;
use App\Models\Customer;
use App\Models\Loan;
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 LoanTopUpStaleTransitionTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_stale_application_submission_after_contract_generation_keeps_top_up_at_advanced_status(): void
    {
        $business = Business::firstOrFail();
        $branch = Branch::create([
            'business_id'=>$business->id,
            'name'=>'Top Up Stale Transition',
            'status'=>'active',
        ]);
        $customer = Customer::create([
            'branch_id'=>$branch->id,
            'customer_number'=>'CUS-TOP-STALE',
            'identity_mode'=>'without_nin',
            'first_name'=>'Asha',
            'last_name'=>'Stale',
            'phone'=>'0756123456',
            'status'=>'active',
        ]);
        $oldProduct = $this->product($business, 'Old Product', 'flat', null);
        $topUpProduct = $this->product($business, 'Top Up Product', 'fixed_amount', '10000.00');
        $oldLoan = Loan::create([
            'branch_id'=>$branch->id,
            'customer_id'=>$customer->id,
            'loan_product_id'=>$oldProduct->id,
            'sequence_number'=>1,
            'sequence_year'=>2026,
            'loan_number'=>'LN-TOP-STALE-OLD',
            'principal'=>'100000.00',
            'interest'=>'0.00',
            'processing_fee'=>'0.00',
            'insurance_fee'=>'0.00',
            'other_charges'=>'0.00',
            'fees'=>'0.00',
            'total_repayment'=>'100000.00',
            'principal_outstanding'=>'20000.00',
            'interest_outstanding'=>'0.00',
            'fees_outstanding'=>'0.00',
            'penalties_outstanding'=>'0.00',
            'total_outstanding'=>'20000.00',
            'total_paid'=>'80000.00',
            'late_payment_penalty_type'=>'none',
            'late_payment_penalty_value'=>'0.000000',
            'purpose'=>'Original loan',
            'schedule_start_date'=>'2026-06-01',
            'status'=>'active',
            'disbursed_at'=>'2026-06-01',
            'activated_at'=>'2026-06-01',
            'schedule_activated_at'=>'2026-06-01',
        ]);

        $manager = User::factory()->create([
            'name'=>'Top Up Manager',
            'username'=>'topup_stale_manager',
            'status'=>'active',
            'primary_branch_id'=>$branch->id,
        ]);
        $manager->roles()->attach(Role::where('name','branch-manager')->firstOrFail());
        $manager->branches()->attach($branch->id,['is_primary'=>true]);

        $this->actingAs($manager)->post(route('loan-top-ups.store',$oldLoan),[
            'loan_product_id'=>$topUpProduct->id,
            'principal'=>'120000.00',
            'purpose'=>'Business stock top-up',
            'schedule_start_date'=>'2026-09-01',
        ])->assertRedirect()->assertSessionHasNoErrors();

        $replacement = Loan::where('top_up_source_loan_id',$oldLoan->id)->firstOrFail();
        $this->assertSame('draft',$replacement->status);

        // Generating a contract advances the server-side workflow while the download can leave
        // the original browser page showing the stale draft -> application_submitted action.
        $replacement->update([
            'status'=>'contract_generated',
            'contract_generated_at'=>now(),
            'contract_generated_by'=>$manager->id,
        ]);

        $this->actingAs($manager)->post(route('loans.transition',$replacement),[
            'status'=>'application_submitted',
            'notes'=>'Submitted from the page that was open before contract generation.',
        ])->assertRedirect()->assertSessionHasNoErrors();

        $replacement->refresh();
        $this->assertSame('contract_generated',$replacement->status);
        $this->assertNotNull($replacement->submitted_at);
        $this->assertDatabaseMissing('loan_status_histories',[
            'loan_id'=>$replacement->id,
            'from_status'=>'contract_generated',
            'to_status'=>'application_submitted',
        ]);
    }

    private function product(Business $business, string $name, string $method, ?string $fixedInterest): LoanProduct
    {
        return LoanProduct::create([
            'business_id'=>$business->id,
            'name'=>$name,
            'minimum_amount'=>'1000.00',
            'maximum_amount'=>'500000.00',
            'duration'=>1,
            'duration_unit'=>'months',
            'interest_rate'=>'0.000000',
            'interest_calculation_method'=>$method,
            'fixed_interest_amount'=>$fixedInterest,
            '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',
        ]);
    }
}
