<?php

namespace Tests\Feature;

use App\Models\AuditLog;
use App\Models\Branch;
use App\Models\Business;
use App\Models\ContractTemplate;
use App\Models\Customer;
use App\Models\Loan;
use App\Models\LoanProduct;
use App\Models\User;
use Database\Seeders\DatabaseSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ContractTemplateDeletionTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_unused_non_default_template_can_be_deleted_from_template_list(): void
    {
        $admin = User::where('username', 'admin')->firstOrFail();
        $template = $this->createTemplate(false);

        $this->actingAs($admin)->get(route('admin.contract-templates.index'))
            ->assertOk()
            ->assertSee($template->name)
            ->assertSee('Delete');

        $response = $this->actingAs($admin)->delete(route('admin.contract-templates.destroy', $template));

        $response->assertRedirect(route('admin.contract-templates.index'));
        $response->assertSessionHas('success');
        $this->assertDatabaseMissing('contract_templates', ['id' => $template->id]);
        Storage::disk('local')->assertMissing($template->file_path);
        $this->assertTrue(AuditLog::where('action', 'contract_template.deleted')->where('auditable_id', $template->id)->exists());
    }

    public function test_default_template_must_be_replaced_before_deletion(): void
    {
        $admin = User::where('username', 'admin')->firstOrFail();
        $template = $this->createTemplate(true);

        $this->actingAs($admin)->get(route('admin.contract-templates.index'))
            ->assertOk()
            ->assertSee('Default protected');

        $response = $this->actingAs($admin)->from(route('admin.contract-templates.index'))
            ->delete(route('admin.contract-templates.destroy', $template));

        $response->assertRedirect(route('admin.contract-templates.index'));
        $response->assertSessionHasErrors('contract_template');
        $this->assertDatabaseHas('contract_templates', ['id' => $template->id, 'is_default' => 1]);
        Storage::disk('local')->assertExists($template->file_path);
    }

    public function test_template_used_by_loan_is_preserved_for_contract_history(): void
    {
        $admin = User::where('username', 'admin')->firstOrFail();
        $template = $this->createTemplate(false);
        $loan = $this->createLoan();
        $loan->update(['contract_template_id' => $template->id]);

        $this->actingAs($admin)->get(route('admin.contract-templates.index'))
            ->assertOk()
            ->assertSee('In use');

        $response = $this->actingAs($admin)->from(route('admin.contract-templates.index'))
            ->delete(route('admin.contract-templates.destroy', $template));

        $response->assertRedirect(route('admin.contract-templates.index'));
        $response->assertSessionHasErrors('contract_template');
        $this->assertDatabaseHas('contract_templates', ['id' => $template->id]);
        $this->assertDatabaseHas('loans', ['id' => $loan->id, 'contract_template_id' => $template->id]);
        Storage::disk('local')->assertExists($template->file_path);
    }

    private function createTemplate(bool $default): ContractTemplate
    {
        $business = Business::firstOrFail();
        $admin = User::where('username', 'admin')->firstOrFail();
        $path = 'contract-templates/'.$business->id.'/delete-test-'.($default ? 'default' : 'unused').'.docx';
        Storage::disk('local')->put($path, 'test contract bytes');

        return ContractTemplate::create([
            'business_id' => $business->id,
            'name' => $default ? 'Protected Default Contract' : 'Unused Contract Template',
            'version' => 1,
            'original_name' => 'contract.docx',
            'format' => 'docx',
            'file_path' => $path,
            'extracted_text' => 'Contract template',
            'blocks' => [],
            'mappings' => [],
            'required_signatories' => ['borrower'],
            'status' => 'active',
            'is_default' => $default,
            'uploaded_by' => $admin->id,
            'updated_by' => $admin->id,
        ]);
    }

    private function createLoan(): Loan
    {
        $business = Business::firstOrFail();
        $admin = User::where('username', 'admin')->firstOrFail();
        $branch = Branch::create([
            'business_id' => $business->id,
            'name' => 'Template History Branch',
            'location' => 'Dodoma',
            'status' => 'active',
        ]);
        $customer = Customer::create([
            'branch_id' => $branch->id,
            'customer_number' => 'CUS-TEMPLATE-HISTORY',
            'identity_mode' => 'without_nin',
            'first_name' => 'Template',
            'last_name' => 'History',
            'gender' => 'male',
            'phone' => '0712111222',
            'occupation' => 'Trader',
            'marital_status' => 'single',
            'status' => 'active',
        ]);
        $product = LoanProduct::create([
            'business_id' => $business->id,
            'name' => 'Template History Product',
            'minimum_amount' => '1000.00',
            'maximum_amount' => '50000.00',
            'duration' => 1,
            'duration_unit' => 'months',
            'interest_rate' => '0.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',
            'processing_fee_payment_mode' => 'financed',
            'insurance_fee_type' => 'fixed',
            'insurance_fee_value' => '0.000000',
            'other_charges' => '0.00',
            'collateral_required' => false,
            'guarantor_required' => false,
            'status' => 'active',
        ]);

        return Loan::create([
            'branch_id' => $branch->id,
            'customer_id' => $customer->id,
            'loan_product_id' => $product->id,
            'sequence_number' => 1,
            'sequence_year' => 2026,
            'loan_number' => 'LN-TEMPLATE-HISTORY-1',
            'principal' => '10000.00',
            'interest' => '0.00',
            'processing_fee' => '0.00',
            'processing_fee_payment_mode' => 'financed',
            'insurance_fee' => '0.00',
            'other_charges' => '0.00',
            'fees' => '0.00',
            'total_repayment' => '10000.00',
            'purpose' => 'Contract history test',
            'schedule_start_date' => '2026-08-15',
            'status' => 'draft',
            'created_by' => $admin->id,
            'updated_by' => $admin->id,
        ]);
    }
}
