<?php

namespace Tests\Feature\Pwa;

use App\Models\Company;
use App\Models\CompanyFinancialSettings;
use App\Models\Credit;
use App\Models\Partner;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Laravel\Sanctum\Sanctum;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

class SimplifiedInputExpandTest extends TestCase
{
    use DatabaseTransactions;

    public function test_simplified_input_gating_is_master_only_ignoring_context(): void
    {
        $on = new CompanyFinancialSettings([
            'simplified_input_enabled' => true,
            'simplified_input_multiplier' => 1000,
            'simplified_input_contexts' => [],
        ]);
        $this->assertTrue($on->isSimplifiedInputEnabled());
        $this->assertTrue($on->isSimplifiedInputEnabled('pwa_credit_create'));
        $this->assertTrue($on->isSimplifiedInputEnabled('pwa_expense_create'));

        $off = new CompanyFinancialSettings(['simplified_input_enabled' => false]);
        $this->assertFalse($off->isSimplifiedInputEnabled());
        $this->assertFalse($off->isSimplifiedInputEnabled('pwa_credit_create'));
    }

    public function test_settings_payload_reports_master_for_all_simplified_flags(): void
    {
        [$admin, $company] = $this->makeAdmin();
        CompanyFinancialSettings::forCompany($company->id)->update([
            'simplified_input_enabled' => true,
            'simplified_input_contexts' => [],
        ]);
        Sanctum::actingAs($admin->fresh());

        // Nota: GET /api/pwa/settings (index()) devuelve buildSettingsPayload()
        // directamente, SIN envoltorio 'settings' (a diferencia de update(), que
        // sí lo envuelve). Se usa el path real de la respuesta.
        $si = $this->getJson('/api/pwa/settings')->assertOk()->json('simplified_input');
        $this->assertTrue($si['enabled']);
        $this->assertTrue($si['credit_enabled']);
        $this->assertTrue($si['payment_enabled']);
    }

    public function test_expense_converts_simplified_amount_when_master_enabled(): void
    {
        [$admin, $company] = $this->makeAdmin();
        CompanyFinancialSettings::forCompany($company->id)->update([
            'simplified_input_enabled' => true, 'simplified_input_multiplier' => 1000,
        ]);
        Sanctum::actingAs($admin->fresh());
        $this->postJson('/api/pwa/expenses', [
            'amount' => 1500, 'category' => 'rent', 'is_simplified_amount' => true,
        ])->assertStatus(201);
        $this->assertDatabaseHas('expenses', ['company_id' => $company->id, 'amount' => 1500000]);
    }

    public function test_expense_converts_by_flag_even_when_master_off(): void
    {
        // Como el lote (PWA-010): el flag dice cómo se escribió el número, no
        // cómo está la empresa hoy. Un teléfono con los ajustes viejos en caché
        // manda el flag después de que la empresa apagó el modo.
        [$admin, $company] = $this->makeAdmin();
        CompanyFinancialSettings::forCompany($company->id)->update([
            'simplified_input_enabled' => false, 'simplified_input_multiplier' => 1000,
        ]);
        Sanctum::actingAs($admin->fresh());
        $this->postJson('/api/pwa/expenses', [
            'amount' => 1500, 'category' => 'rent', 'is_simplified_amount' => true,
        ])->assertStatus(201);
        $this->assertDatabaseHas('expenses', ['company_id' => $company->id, 'amount' => 1500000]);
    }

    public function test_partner_contribution_converts_simplified_amount(): void
    {
        [$admin, $company] = $this->makeAdmin();
        CompanyFinancialSettings::forCompany($company->id)->update([
            'simplified_input_enabled' => true, 'simplified_input_multiplier' => 1000,
        ]);
        // No existe PartnerFactory: se crea el registro mínimo directamente.
        // 'joined_at' es requerido (no-nullable, sin default) según la migración.
        $partner = Partner::create([
            'company_id' => $company->id,
            'name' => 'Socio de Prueba',
            'joined_at' => now(),
        ]);
        Sanctum::actingAs($admin->fresh());
        $this->postJson("/api/pwa/partners/{$partner->id}/transaction", [
            'transaction_type' => 'contribution', 'contribution_type' => 'additional',
            'amount' => 1500, 'is_simplified_amount' => true,
        ])->assertStatus(201);
        $this->assertDatabaseHas('capital_contributions', ['company_id' => $company->id, 'amount' => 1500000]);
    }

    public function test_visit_converts_simplified_promised_amount(): void
    {
        [$admin, $company] = $this->makeAdmin();
        CompanyFinancialSettings::forCompany($company->id)->update([
            'simplified_input_enabled' => true, 'simplified_input_multiplier' => 1000,
        ]);
        $credit = Credit::factory()->create(['company_id' => $company->id]);
        Sanctum::actingAs($admin->fresh());
        $this->postJson('/api/pwa/visits', [
            'credit_id' => $credit->id, 'visit_type' => 'no_payment',
            'reason' => 'no_money', 'visit_date' => now()->toDateString(),
            'promised_amount' => 1500, 'is_simplified_amount' => true,
        ])->assertStatus(201);
        $this->assertDatabaseHas('collection_visits', ['company_id' => $company->id, 'promised_amount' => 1500000]);
    }

    /** @return array{0: User, 1: Company} */
    private function makeAdmin(): array
    {
        Role::firstOrCreate(['name' => 'admin', 'guard_name' => 'web']);
        $company = Company::factory()->create();
        $plan = Plan::factory()->create(['has_pwa_access' => true]);
        Subscription::factory()->active()->create([
            'company_id' => $company->id, 'plan_id' => $plan->id, 'ends_at' => now()->addYear(),
        ]);
        $admin = User::factory()->create(['company_id' => $company->id]);
        $admin->assignRole('admin');

        return [$admin, $company];
    }
}
