<?php

namespace Tests\Feature\Api;

use App\Models\ApiRequestLog;
use App\Services\Api\Severidad;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Str;
use Tests\TestCase;

/**
 * La columna `severity` de `api_request_logs`.
 *
 * Lo que se fija aquí no es la clasificación —eso está en `SeveridadTest`— sino que
 * **la fila se clasifique sola**. El valor por defecto de la columna es `ok`, así que una
 * fila creada sin clasificar no falla: **miente**. Y eso es peor.
 */
class SeverityColumnTest extends TestCase
{
    use RefreshDatabase;

    private function peticion(array $extra = []): ApiRequestLog
    {
        return ApiRequestLog::create(array_merge([
            'request_uuid' => (string) Str::uuid(),
            'method' => 'POST',
            'path' => 'api/v1',
            'ip' => '203.0.113.20',
            'auth_type' => 'bearer',
            'http_status' => 200,
            'action' => 'products',
            'host' => 'https://sitio.test',
            'started_at' => now(),
            'ended_at' => now(),
            'duration_ms' => 20,
        ], $extra));
    }

    public function test_una_peticion_correcta_se_guarda_como_ok(): void
    {
        $this->assertSame(Severidad::OK, $this->peticion()->severity);
    }

    public function test_el_modelo_clasifica_solo_sin_que_nadie_se_acuerde(): void
    {
        // **El caso que rompió dos tests al añadir la columna.** El middleware la
        // rellenaba, pero cualquier otra vía de inserción —tests, seeders, comandos—
        // dejaba el valor por defecto `ok` en una petición que había fallado. Es la misma
        // trampa que el puntero de soporte que estaba a NULL en toda la base (MGR-045):
        // un campo derivado que hay que acordarse de rellenar acaba mal.
        $fallida = $this->peticion([
            'http_status' => 401,
            'error_code' => 401,
            'error' => 'Token no válido',
        ]);

        $this->assertSame(Severidad::ERROR, $fallida->severity);
    }

    public function test_un_404_de_sin_contenido_no_se_guarda_como_error(): void
    {
        $sinContenido = $this->peticion([
            'http_status' => 404,
            'error_code' => 3002,
            'error' => 'No compatible features version found for this product version',
        ]);

        $this->assertSame(Severidad::SIN_CONTENIDO, $sinContenido->severity);
    }

    public function test_se_respeta_la_severidad_si_se_pasa_a_mano(): void
    {
        // Para poder rectificar una clasificación sin pelearse con el modelo.
        $fila = $this->peticion([
            'http_status' => 500,
            'severity' => Severidad::NEGOCIO,
        ]);

        $this->assertSame(Severidad::NEGOCIO, $fila->severity);
    }

    public function test_el_porcentaje_de_error_solo_cuenta_los_errores_de_verdad(): void
    {
        // Es la razón de ser de la columna: con el criterio antiguo, estas cuatro filas
        // daban un 75 % de error. De verdad es un 25 %.
        $this->peticion();
        $this->peticion(['http_status' => 401, 'error_code' => 401, 'error' => 'Token no válido']);
        $this->peticion(['http_status' => 404, 'error_code' => 3002, 'error' => 'No compatible setup configuration found']);
        $this->peticion(['http_status' => 401, 'error_code' => 2001, 'error' => 'Licence does not include this plugin']);

        $this->assertSame(4, ApiRequestLog::count());
        $this->assertSame(3, ApiRequestLog::where('http_status', '>=', 400)->count());
        $this->assertSame(1, ApiRequestLog::where('severity', Severidad::ERROR)->count());
        $this->assertSame(1, ApiRequestLog::where('severity', Severidad::SIN_CONTENIDO)->count());
        $this->assertSame(1, ApiRequestLog::where('severity', Severidad::NEGOCIO)->count());
    }
}
