<?php

namespace Tests\Feature\Dashboard;

use App\Models\Auth\User;
use App\Models\Clients\Client;
use App\Models\Environments\Environment;
use App\Models\Monitoring\Log as MonitoringLog;
use App\Models\Products\LicenseToken;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Spatie\Permission\Models\Permission;
use Tests\TestCase;

/**
 * Bienvenida de la cabecera: saludo + una frase que responde "¿tengo algo que
 * hacer?" sin leer nada más (diseño "Dashboard Manager" de Claude Design).
 *
 * Lo que se fija: que la frase cambie con los datos REALES y no sea decorativa.
 * Una bienvenida que dice "todo en orden" habiendo un crítico es peor que no
 * tenerla.
 */
class WelcomeTest extends TestCase
{
    use RefreshDatabase;

    private function admin(string $nombre = 'Antonio'): User
    {
        $permisos = [
            'admin.dashboard.index',
            'admin.environments.index',
            'admin.clients.index',
            'admin.license-tokens.index',
            'admin.products.index',
            'admin.api-logs.index',
        ];

        foreach ($permisos as $p) {
            Permission::firstOrCreate(
                ['name' => $p, 'guard_name' => 'web'],
                ['model' => 'dashboard', 'description' => $p]
            );
        }

        $user = User::factory()->create(['name' => $nombre]);
        $user->givePermissionTo($permisos);
        $this->actingAs($user);

        Cache::flush();

        return $user;
    }

    /** Un cliente cualquiera, para que la instalación no cuente como vacía. */
    private function conDatos(): Client
    {
        return Client::create(['name' => 'Cliente Base', 'shortname' => 'base', 'actived' => true]);
    }

    public function test_saluda_por_el_nombre_de_pila(): void
    {
        $this->admin('Antonio');
        $this->conDatos();

        $this->get('/dashboard')
            ->assertOk()
            ->assertSee('Hola, Antonio')
            // `users` sólo tiene `name`: no hay apellido que añadir al saludo.
            ->assertDontSee('Hola, Antonio Manzano');
    }

    public function test_si_name_trae_el_nombre_completo_solo_usa_el_primero(): void
    {
        // Hay instalaciones con el nombre completo metido en `name`.
        $this->admin('María José Pérez');
        $this->conDatos();

        $this->get('/dashboard')
            ->assertOk()
            ->assertSee('Hola, María');
    }

    public function test_instalacion_vacia_invita_a_empezar(): void
    {
        $this->admin();

        $this->get('/dashboard')
            ->assertOk()
            ->assertSee('Crea tu primer cliente para empezar');
    }

    public function test_sin_incidencias_lo_dice_explicitamente(): void
    {
        $this->admin();
        $this->conDatos();

        $this->get('/dashboard')
            ->assertOk()
            ->assertSee('Todo en orden. Nada pendiente de tu parte.');
    }

    public function test_con_criticos_dice_cuantos(): void
    {
        $this->admin();
        $cliente = $this->conDatos();

        // Un entorno que dejó de sincronizar hace más de 7 días es crítico.
        foreach (['uno', 'dos'] as $i => $slug) {
            Environment::create([
                'name' => 'Entorno ' . $slug,
                'domain' => 'https://' . $slug . '.test',
                'version' => '4.5.3',
                'env' => 'pro',
                'client_id' => $cliente->id,
                'active' => true,
                'refresh_at' => now()->subDays(20 + $i),
            ]);
        }

        $this->get('/dashboard')
            ->assertOk()
            ->assertSee('2 incidencias críticas requieren tu atención.');
    }

    public function test_con_un_solo_critico_habla_en_singular(): void
    {
        $this->admin();
        $cliente = $this->conDatos();

        MonitoringLog::db('danger', '16003', 'Algo crítico', 'ApiRateEvent', '1');

        $this->get('/dashboard')
            ->assertOk()
            ->assertSee('1 incidencia crítica requiere tu atención.');
    }

    public function test_solo_con_avisos_no_dramatiza(): void
    {
        $this->admin();
        $cliente = $this->conDatos();

        LicenseToken::create([
            'client_id' => $cliente->id,
            'name' => 'Licencia que vence',
            'token' => '3IP-BIENVENIDA',
            'active' => true,
            'end_at' => now()->addDays(20),
        ]);

        $this->get('/dashboard')
            ->assertOk()
            ->assertSee('Tienes 1 aviso pendiente de revisar.')
            ->assertDontSee('crítica');
    }
}
