<?php
namespace Tests\Feature;

use App\Models\Account;
use App\Models\DepreciationRun;
use App\Models\DocumentSequence;
use App\Models\FixedAsset;
use App\Services\DepreciationService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Validation\ValidationException;
use Tests\TestCase;

class DepreciationTest extends TestCase {
    use RefreshDatabase;

    protected function setUp(): void {
        parent::setUp();
        Account::create(['code' => '5260', 'name' => 'Depreciation', 'account_type' => 'expense']);
        Account::create(['code' => '1510', 'name' => 'Accumulated Depreciation', 'account_type' => 'asset']);
        DocumentSequence::create(['key' => 'journal', 'label' => 'Journal Voucher', 'prefix' => 'JV', 'next_number' => 1, 'padding' => 5, 'include_fy' => true]);
        FixedAsset::create(['asset_no' => 'FA-TEST-1', 'name' => 'Test Crusher', 'purchase_cost' => 120000,
            'salvage_value' => 0, 'useful_life_years' => 5, 'accumulated_depreciation' => 0,
            'net_book_value' => 120000, 'status' => 'active']);
    }

    public function test_run_posts_balanced_journal_and_moves_nbv(): void {
        $run = DepreciationService::run('2026-09');
        $this->assertSame(2000.0, (float) $run->total_amount); // 120000 / 60
        $this->assertDatabaseHas('journals', ['id' => $run->journal_id, 'total_debit' => 2000.0, 'total_credit' => 2000.0, 'source_module' => 'depreciation']);
        $this->assertSame(118000.0, (float) FixedAsset::first()->net_book_value);
        $this->assertSame(2000.0, (float) Account::where('code', '5260')->value('current_balance'));
        $this->assertSame(-2000.0, (float) Account::where('code', '1510')->value('current_balance'));
    }

    public function test_duplicate_period_blocked(): void {
        DepreciationService::run('2026-09');
        $this->expectException(ValidationException::class);
        DepreciationService::run('2026-09');
    }

    public function test_charge_capped_at_salvage_floor(): void {
        $a = FixedAsset::first();
        $a->update(['accumulated_depreciation' => 119500, 'net_book_value' => 500, 'salvage_value' => 0]);
        $this->assertSame(500.0, DepreciationService::monthlyCharge($a));
        $a->update(['accumulated_depreciation' => 120000, 'net_book_value' => 0]);
        $this->assertSame(0.0, DepreciationService::monthlyCharge($a));
    }
}
