<?php

namespace Tests\Feature\Api;

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

/**
 * `isstandard`: si un plugin viene con Moodle. Lo manda `local_tresipunt` desde el
 * 2026-10-01 en cada plugin, y solo lo sabe el propio Moodle del sitio.
 *
 * Se guarda tal cual en `plugins.isstandard`, y lo que no se entienda queda como «no se
 * sabe»: un valor raro **no puede tumbar un `sync`**, porque se perdería el inventario entero
 * del día por un dato que solo sirve para clasificar.
 */
class PluginEstandarTest extends TestCase
{
    use RefreshDatabase;

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

    private Environment $entorno;

    protected function setUp(): void
    {
        parent::setUp();

        $cliente = Client::create(['name' => 'Cliente Estándar', 'shortname' => 'std', 'actived' => true]);
        $token = LicenseToken::create(['client_id' => $cliente->id, 'name' => 'Licencia', 'token' => self::TOKEN, 'active' => true]);

        $this->entorno = Environment::create([
            'name' => 'Campus Estándar',
            'domain' => self::DOMAIN,
            'version' => '5.1.1',
            'env' => 'pro',
            'client_id' => $cliente->id,
            'license_token_id' => $token->id,
            'active' => true,
        ]);
    }

    /** @param  array<int, array<string, mixed>>  $plugins */
    private function enviar(string $accion, array $plugins): \Illuminate\Testing\TestResponse
    {
        return $this->withHeaders(['Authorization' => 'Bearer ' . self::TOKEN, 'Accept' => 'application/json'])
            ->postJson('/api/v1', [
                'action' => $accion,
                'host' => self::DOMAIN,
                'plugin' => 'local_tresipunt',
                'version' => '2026100100',
                'site' => ['version' => '2025100601.03', 'release' => '5.1.1'],
                'data' => ['plugins' => $plugins],
            ]);
    }

    private function plugin(string $component, array $extra = []): array
    {
        return array_merge([
            'name' => $component,
            'component' => $component,
            'type' => strtok($component, '_'),
            'versiondisk' => '2026010100',
            'versiondb' => '2026010100',
        ], $extra);
    }

    private function guardado(string $component): ?bool
    {
        return Plugin::where('environment_id', $this->entorno->id)->where('component', $component)->firstOrFail()->isstandard;
    }

    public function test_el_sync_guarda_si_es_estandar(): void
    {
        $this->enviar('sync', [
            $this->plugin('mod_assign', ['isstandard' => true]),
            $this->plugin('mod_customcert', ['isstandard' => false]),
            $this->plugin('mod_antiguo'),
        ])->assertSuccessful();

        $this->assertTrue($this->guardado('mod_assign'));
        $this->assertFalse($this->guardado('mod_customcert'));
        $this->assertNull($this->guardado('mod_antiguo'), 'un plugin anterior no lo manda: no se sabe');
    }

    public function test_la_accion_plugins_tambien_lo_guarda(): void
    {
        $this->enviar('plugins', [
            $this->plugin('mod_assign', ['isstandard' => true]),
            $this->plugin('mod_customcert', ['isstandard' => false]),
        ])->assertSuccessful();

        $this->assertTrue($this->guardado('mod_assign'));
        $this->assertFalse($this->guardado('mod_customcert'));
    }

    /** @return array<string, array{mixed, ?bool}> */
    public static function formas(): array
    {
        return [
            'true' => [true, true],
            'false' => [false, false],
            'uno' => [1, true],
            'cero' => [0, false],
            'cadena uno' => ['1', true],
            'cadena true' => ['TRUE', true],
            'cadena false' => ['false', false],
            'texto raro' => ['quizás', null],
            'lista' => [['si'], null],
            'nulo' => [null, null],
        ];
    }

    /**
     * @dataProvider formas
     */
    public function test_cualquier_forma_se_lee_sin_tumbar_el_sync(mixed $enviado, ?bool $esperado): void
    {
        $this->enviar('sync', [$this->plugin('mod_algo', ['isstandard' => $enviado])])->assertSuccessful();

        $this->assertSame($esperado, $this->guardado('mod_algo'));
    }
}
