<?php

namespace Tests\Feature\Api;

use App\Models\Clients\Client;
use App\Models\Environments\Environment;
use App\Models\Products\LicenseToken;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

/**
 * Interruptores que cortan el servicio a un Moodle.
 *
 * Antes solo existía uno efectivo —desactivar el token— mientras el panel ofrecía
 * otros dos que no cortaban nada: desactivar el entorno y desactivar (o borrar) el
 * cliente. Ver known-issues MGR-021.
 *
 * Estos son además los primeros tests del contrato de la API (MGR-019).
 */
class ServiceGatesTest extends TestCase
{
    use RefreshDatabase;

    private const TOKEN = '3IP-TEST-GATE-0001';
    private const DOMAIN = 'https://gate.test';

    private function seedLicensedEnvironment(): array
    {
        $client = Client::create([
            'name' => 'Cliente Puerta',
            'shortname' => 'puerta',
            'actived' => true,
        ]);

        $token = LicenseToken::create([
            'client_id' => $client->id,
            'name' => 'Licencia Puerta',
            'token' => self::TOKEN,
            'active' => true,
        ]);

        $environment = Environment::create([
            'name' => 'Entorno Puerta',
            'domain' => self::DOMAIN,
            'version' => '5.1.1',
            'env' => 'local',
            'client_id' => $client->id,
            'license_token_id' => $token->id,
            'active' => true,
        ]);

        return [$client, $token, $environment];
    }

    private function callProducts(): \Illuminate\Testing\TestResponse
    {
        return $this->withHeaders([
            'Authorization' => 'Bearer ' . self::TOKEN,
            'Accept' => 'application/json',
        ])->postJson('/api/v1', [
            'action' => 'products',
            'host' => self::DOMAIN,
            'plugin' => 'local_tresipunt',
            'version' => '2026080604',
            'site' => [
                'version' => '2025100601.03',
                'release' => '5.1.1+ (Build: 20251219)',
                'type' => 'moodle',
                'env' => 'local',
            ],
        ]);
    }

    public function test_con_todo_activo_la_api_responde(): void
    {
        $this->seedLicensedEnvironment();

        $this->callProducts()
            ->assertOk()
            ->assertJsonPath('success', true);
    }

    public function test_token_inactivo_corta_el_servicio(): void
    {
        [, $token] = $this->seedLicensedEnvironment();
        $token->update(['active' => false]);

        $this->callProducts()
            ->assertForbidden()
            ->assertJsonPath('error', 'Token inactivo');
    }

    public function test_cliente_inactivo_corta_el_servicio(): void
    {
        [$client] = $this->seedLicensedEnvironment();
        $client->update(['actived' => false]);

        $this->callProducts()
            ->assertForbidden()
            ->assertJsonPath('error', 'Cliente inactivo');
    }

    public function test_cliente_borrado_corta_el_servicio(): void
    {
        [$client] = $this->seedLicensedEnvironment();
        $client->delete();

        // `Client` usa SoftDeletes: la relación devuelve null y el corte es el mismo.
        // Esto es lo que describía el issue original y hoy no tiene UI que lo provoque.
        $this->callProducts()
            ->assertForbidden()
            ->assertJsonPath('error', 'Cliente inactivo');
    }

    public function test_entorno_inactivo_corta_el_servicio(): void
    {
        [, , $environment] = $this->seedLicensedEnvironment();
        $environment->update(['active' => false]);

        $this->callProducts()
            ->assertForbidden()
            ->assertJsonPath('error', 'Entorno inactivo');
    }

    public function test_entorno_borrado_deja_de_encontrarse(): void
    {
        [, , $environment] = $this->seedLicensedEnvironment();
        $environment->delete();

        // El hasMany filtra los borrados lógicos, así que el host deja de casar.
        // No es 403: es el 401 de "host no vinculado a este token".
        $this->callProducts()->assertUnauthorized();
    }
}
