<?php

namespace Tests\Feature\Monitoring;

use App\Models\Monitoring\Log as MonitoringLog;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Schema;
use Tests\TestCase;

/**
 * `logs.entity_id` tiene que aceptar referencias que no sean números.
 *
 * **El fallo que fija.** La columna era `int` y `Log::db()` declara `?string $id`, así
 * que registrar un bloqueo manual —cuya referencia es la IP, `'203.0.113.5'`— lanzaba
 * `SQLSTATE[HY000] 1366 Incorrect integer value` en MariaDB. **Bloquear una IP a mano
 * habría petado en producción.**
 *
 * **Y por qué hace falta comprobar el tipo de la columna y no solo insertar.** El test
 * que ya existía —`test_un_administrador_bloquea_una_ip_a_mano`— insertaba esa fila y
 * pasaba, porque **sqlite guarda una cadena en una columna `integer` sin protestar**. La
 * suite era más permisiva que producción, que es peor que ser más estricta: no avisa.
 *
 * Por eso aquí se mira **el tipo declarado**, que es lo único que se comporta igual en
 * los dos motores.
 */
class LogEntityIdTest extends TestCase
{
    use RefreshDatabase;

    public function test_entity_id_no_es_una_columna_entera(): void
    {
        // Es la comprobación que sqlite no puede hacer por su cuenta: el tipo.
        $tipo = Schema::getColumnType('logs', 'entity_id');

        $this->assertNotContains(
            $tipo,
            ['integer', 'int', 'bigint', 'smallint'],
            'entity_id volvió a ser numérica: un bloqueo por IP no se podrá registrar en MariaDB'
        );
    }

    public function test_se_puede_registrar_un_bloqueo_por_ip(): void
    {
        MonitoringLog::db('warning', '16011', 'IP bloqueada a mano: 203.0.113.5', 'ApiBlock', '203.0.113.5');

        $log = MonitoringLog::where('code', '16011')->firstOrFail();

        // La IP se guarda tal cual, sin convertirse en 0 ni en null.
        $this->assertSame('203.0.113.5', $log->entity_id);
    }

    public function test_se_puede_registrar_una_referencia_a_un_ajuste(): void
    {
        // El caso que lo destapó: la clave de un ajuste como referencia.
        MonitoringLog::db('info', '16014', 'Destinatario recuperado', 'Config', 'alerts:support:email');

        $this->assertSame(
            'alerts:support:email',
            MonitoringLog::where('code', '16014')->value('entity_id')
        );
    }

    public function test_las_referencias_numericas_siguen_funcionando(): void
    {
        // `Log::enlace()` hace `(int) $entity_id` para las entidades con pantalla, así que
        // esas tienen que seguir guardando un id numérico legible.
        MonitoringLog::db('info', '16019', 'Cliente reactivado', 'Client', '42');

        $log = MonitoringLog::where('code', '16019')->firstOrFail();

        $this->assertSame('42', $log->entity_id);
        $this->assertSame(42, (int) $log->entity_id);
    }
}
