<?php

declare(strict_types=1);

namespace Tests\Feature\Security;

use App\Models\Company;
use App\Models\Plan;
use App\Models\Subscription;
use App\Models\User;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use PHPUnit\Framework\Attributes\Test;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

/**
 * FIX C-01: Verifica que las habilidades del token Sanctum se validan en EnsurePwaAccess.
 *
 * Escenarios:
 *  1. Token con pwa:collector → pasa EnsurePwaAccess (200)
 *  2. Token con habilidad arbitraria (sin pwa:*) → rechazado (403)
 *  3. Token con habilidad '*' comodín → rechazado (403)
 *  4. Token de admin (pwa:admin) → pasa EnsurePwaAccess (200)
 *  5. Token de supervisor (pwa:supervisor) → pasa EnsurePwaAccess (200)
 */
class TokenAbilityTest extends TestCase
{
    use DatabaseTransactions;

    private Company $company;

    protected function setUp(): void
    {
        parent::setUp();

        foreach (['admin', 'supervisor', 'collector'] as $role) {
            Role::firstOrCreate(['name' => $role, 'guard_name' => 'web']);
        }

        $plan = Plan::factory()->create();
        $this->company = Company::factory()->create();

        Subscription::factory()->create([
            'company_id' => $this->company->id,
            'plan_id' => $plan->id,
            'status' => Subscription::STATUS_ACTIVE,
            'is_active' => true,
            'starts_at' => now()->subMonth(),
            'ends_at' => now()->addYear(),
        ]);
    }

    private function makeUser(string $role): User
    {
        $user = User::factory()->create(['company_id' => $this->company->id]);
        $user->assignRole($role);

        return $user->fresh();
    }

    #[Test]
    public function collector_token_with_pwa_ability_passes_pwa_access(): void
    {
        $user = $this->makeUser('collector');
        $token = $user->createToken('device', ['pwa:collector'])->plainTextToken;

        $this->withToken($token)->getJson('/api/pwa/auth/me')
            ->assertStatus(200);
    }

    #[Test]
    public function token_without_pwa_ability_is_rejected_by_middleware(): void
    {
        $user = $this->makeUser('collector');
        $token = $user->createToken('device', ['other:ability'])->plainTextToken;

        $this->withToken($token)->getJson('/api/pwa/auth/me')
            ->assertStatus(403)
            ->assertJson(['message' => 'Token sin permisos PWA. Inicia sesión nuevamente.']);
    }

    #[Test]
    public function token_with_wildcard_ability_is_rejected_by_middleware(): void
    {
        $user = $this->makeUser('collector');
        // Sanctum '*' comodín: tokenCan('pwa:collector') retorna false → debe ser rechazado
        $token = $user->createToken('device', ['*'])->plainTextToken;

        $this->withToken($token)->getJson('/api/pwa/auth/me')
            ->assertStatus(403);
    }

    #[Test]
    public function admin_token_with_pwa_admin_ability_passes_pwa_access(): void
    {
        $user = $this->makeUser('admin');
        $token = $user->createToken('device', ['pwa:admin'])->plainTextToken;

        $this->withToken($token)->getJson('/api/pwa/auth/me')
            ->assertStatus(200);
    }

    #[Test]
    public function supervisor_token_with_pwa_supervisor_ability_passes_pwa_access(): void
    {
        $user = $this->makeUser('supervisor');
        $token = $user->createToken('device', ['pwa:supervisor'])->plainTextToken;

        $this->withToken($token)->getJson('/api/pwa/auth/me')
            ->assertStatus(200);
    }
}
