<?php

namespace Tests\Feature\Environments;

use App\Livewire\Plugins\Inventario as PluginsDelParque;
use App\Models\Auth\User;
use App\Models\Clients\Client;
use App\Models\Environments\Environment;
use App\Models\Environments\Plugin;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Livewire;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Models\Role;
use Tests\TestCase;

/**
 * El buscador de plugins del parque y su desplegable de sugerencias.
 *
 * **Lo que se rompía.** El desplegable no tenía estado: se pintaba siempre que hubiera
 * sugerencias, y las sugerencias salen del propio texto buscado. Al elegir una, el término
 * pasaba a ser ese identificador… que sigue encajando, así que la lista se volvía a pintar
 * encima de la tabla y no había forma de quitarla.
 *
 * Y no hace falta un caso raro para verlo: **basta con que dos componentes compartan
 * prefijo**, que es lo normal en una familia de plugins. `local_coursetransfer` encaja
 * también con `local_coursetransfermanager`.
 *
 * El cierre en sí es de Alpine y no se puede comprobar desde PHP. Lo que sí se fija aquí es
 * la otra mitad: **que la opción ya elegida deje de ofrecerse**, porque pulsarla no hacía
 * nada y era lo que daba la sensación de que el desplegable estaba pillado.
 */
class BuscadorDePluginsTest extends TestCase
{
    use RefreshDatabase;

    private function admin(): User
    {
        $rol = Role::firstOrCreate(['name' => 'Admin plugins', 'guard_name' => 'web']);

        foreach (['admin.plugins.index', 'admin.plugins.environment'] as $nombre) {
            $rol->givePermissionTo(Permission::firstOrCreate(
                ['name' => $nombre, 'guard_name' => 'web'],
                ['model' => 'plugins', 'description' => $nombre]
            ));
        }

        $usuario = User::factory()->create();
        $usuario->assignRole($rol);
        $this->actingAs($usuario);

        return $usuario;
    }

    private function entorno(string $nombre): Environment
    {
        $cliente = Client::firstOrCreate(
            ['shortname' => 'bus'],
            ['name' => 'Cliente Buscador', 'actived' => true]
        );

        return Environment::create([
            'name' => $nombre,
            'domain' => 'https://' . str()->slug($nombre) . '.bus.test',
            'env' => 'pro',
            'version' => '5.1.1',
            'client_id' => $cliente->id,
            'active' => true,
            'refresh_at' => now()->subHour(),
        ]);
    }

    private function plugin(Environment $entorno, string $component, string $version): Plugin
    {
        return Plugin::create([
            'environment_id' => $entorno->id,
            'name' => $component,
            'component' => $component,
            'type' => explode('_', $component)[0],
            'versiondisk' => $version,
            'versiondb' => $version,
            'versionrequires' => '2025041400',
            'has_updates' => false,
            'has_dependencies' => false,
        ]);
    }

    /** Los dos componentes que comparten prefijo, en dos entornos. */
    private function laFamilia(): void
    {
        $uno = $this->entorno('Sitio uno');
        $dos = $this->entorno('Sitio dos');

        $this->plugin($uno, 'local_coursetransfer', '2026052700');
        $this->plugin($dos, 'local_coursetransfer', '2026090900');
        $this->plugin($uno, 'local_coursetransfermanager', '2026010100');
    }

    private function sugerenciasCon(string $termino): array
    {
        return Livewire::test(PluginsDelParque::class)
            ->set('busqueda', $termino)
            ->instance()
            ->sugerencias();
    }

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

        $componentes = array_column($this->sugerenciasCon('coursetransfer'), 'component');

        $this->assertContains('local_coursetransfer', $componentes);
        $this->assertContains('local_coursetransfermanager', $componentes);
    }

    public function test_el_que_ya_esta_elegido_deja_de_ofrecerse(): void
    {
        // **Es la mitad del fallo.** Con el término exacto puesto, la lista seguía
        // ofreciendo esa misma opción: pulsarla no cambia nada, y un botón que no puede
        // hacer nada se lee como un desplegable que no responde.
        $this->admin();
        $this->laFamilia();

        $componentes = array_column($this->sugerenciasCon('local_coursetransfer'), 'component');

        $this->assertNotContains('local_coursetransfer', $componentes, 'El elegido no se repite.');
        $this->assertContains('local_coursetransfermanager', $componentes, 'El otro sí: es otro plugin.');
    }

    public function test_con_una_sola_coincidencia_no_hay_desplegable(): void
    {
        // La tabla de abajo ya es la respuesta; el desplegable solo taparía.
        $this->admin();
        $this->laFamilia();

        $this->assertSame([], $this->sugerenciasCon('coursetransfermanager'));
    }

    /* ============ Y lo que se venía a buscar ============ */

    public function test_el_detalle_dice_que_version_tiene_cada_entorno(): void
    {
        // Es la pregunta con la que se entra: «qué versión de este plugin tiene cada
        // sitio». El desplegable de la fila la contesta, y este test la fija.
        $this->admin();
        $this->laFamilia();

        Livewire::test(PluginsDelParque::class)
            ->set('busqueda', 'local_coursetransfer')
            ->call('alternar', 'local_coursetransfer')
            ->assertSee('Sitio uno')
            ->assertSee('Sitio dos')
            ->assertSee('2026052700')
            ->assertSee('2026090900');
    }
}
