<?php

namespace Tests\Feature\Accounting;

use App\Enums\AccountType;
use App\Enums\DocumentStatus;
use App\Enums\NormalBalance;
use App\Models\Account;
use App\Models\AccountingPeriod;
use App\Models\Branch;
use App\Models\Company;
use App\Models\Driver;
use App\Models\DriverAdvance;
use App\Models\DriverSettlement;
use App\Models\FiscalYear;
use App\Services\Accounting\DriverAdvancePostingService;
use App\Services\Accounting\DriverSettlementPostingService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

final class DriverAdvanceSettlementTest extends TestCase
{
    use RefreshDatabase;

    public function test_driver_advance_and_full_settlement_create_balanced_journals(): void
    {
        $company = Company::create([
            'legal_name' => 'Fleet Test LLC',
            'base_currency' => 'AED',
            'timezone' => 'Asia/Dubai',
            'is_active' => true,
        ]);
        $branch = Branch::create([
            'company_id' => $company->id,
            'code' => 'HO',
            'name' => 'Head Office',
            'is_active' => true,
        ]);
        $fiscalYear = FiscalYear::create([
            'company_id' => $company->id,
            'name' => '2026',
            'starts_on' => '2026-01-01',
            'ends_on' => '2026-12-31',
            'status' => 'open',
        ]);
        AccountingPeriod::create([
            'fiscal_year_id' => $fiscalYear->id,
            'name' => 'July 2026',
            'starts_on' => '2026-07-01',
            'ends_on' => '2026-07-31',
            'is_locked' => false,
        ]);

        $cash = $this->account($company->id, '1000', 'Cash', AccountType::ASSET, NormalBalance::DEBIT);
        $driverAdvanceAccount = $this->account($company->id, '1160', 'Driver Advances', AccountType::ASSET, NormalBalance::DEBIT);
        $tripExpense = $this->account($company->id, '5020', 'Driver Trip Cost', AccountType::COST_OF_REVENUE, NormalBalance::DEBIT);
        $driver = Driver::create([
            'company_id' => $company->id,
            'branch_id' => $branch->id,
            'driver_code' => 'DRV-001',
            'name' => 'Test Driver',
            'employment_type' => 'employee',
            'is_active' => true,
        ]);

        $advance = DriverAdvance::create([
            'company_id' => $company->id,
            'branch_id' => $branch->id,
            'driver_id' => $driver->id,
            'advance_number' => 'HO-DADV-2026-000001',
            'advance_date' => '2026-07-10',
            'advance_type' => 'trip',
            'amount' => '1000.0000',
            'settled_amount' => '0.0000',
            'advance_account_id' => $driverAdvanceAccount->id,
            'cash_bank_account_id' => $cash->id,
            'status' => DocumentStatus::APPROVED,
        ]);

        app(DriverAdvancePostingService::class)->post($advance);
        $advance->refresh();
        self::assertSame(DocumentStatus::POSTED, $advance->status);
        self::assertSame('1000.0000', $advance->journal->debit_total);
        self::assertSame('1000.0000', $advance->journal->credit_total);

        $settlement = DriverSettlement::create([
            'company_id' => $company->id,
            'branch_id' => $branch->id,
            'driver_advance_id' => $advance->id,
            'settlement_number' => 'HO-DSET-2026-000001',
            'settlement_date' => '2026-07-11',
            'expense_amount' => '600.0000',
            'cash_refund_amount' => '400.0000',
            'total_settled' => '1000.0000',
            'expense_account_id' => $tripExpense->id,
            'cash_bank_account_id' => $cash->id,
            'status' => DocumentStatus::APPROVED,
        ]);

        app(DriverSettlementPostingService::class)->post($settlement);
        $settlement->refresh();
        $advance->refresh();

        self::assertSame(DocumentStatus::POSTED, $settlement->status);
        self::assertSame('1000.0000', $advance->settled_amount);
        self::assertSame('1000.0000', $settlement->journal->debit_total);
        self::assertSame('1000.0000', $settlement->journal->credit_total);
        self::assertSame('600.0000', (string) $settlement->journal->lines()->where('account_id', $tripExpense->id)->value('debit'));
        self::assertSame('400.0000', (string) $settlement->journal->lines()->where('account_id', $cash->id)->value('debit'));
        self::assertSame('1000.0000', (string) $settlement->journal->lines()->where('account_id', $driverAdvanceAccount->id)->value('credit'));
    }

    private function account(int $companyId, string $code, string $name, AccountType $type, NormalBalance $normalBalance): Account
    {
        return Account::create([
            'company_id' => $companyId,
            'code' => $code,
            'name' => $name,
            'type' => $type,
            'normal_balance' => $normalBalance,
            'is_control_account' => false,
            'is_active' => true,
        ]);
    }
}
