<?php

namespace Tests\Feature\Admin;

use App\Http\Middleware\UUIDCheckMiddleware;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\DB;
use Laravel\Sanctum\Sanctum;
use Tests\Support\CreatesAdminApiUser;
use Tests\TestCase;

class CiudadesAdminTest extends TestCase
{
    use CreatesAdminApiUser;
    use RefreshDatabase;

    private const CITIES_ENDPOINT = '/api/admin/ciudades';
    private const ALIASES_ENDPOINT = '/api/admin/ciudades-aliases';

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

        $this->withoutMiddleware(UUIDCheckMiddleware::class);
        $this->withHeader('X-Requested-With', 'XMLHttpRequest');
    }

    /**
     * Restringe el catálogo oficial a administradores root.
     */
    public function test_requires_root_permissions_for_city_crud(): void
    {
        [$admin] = $this->createAdminApiUser(false);
        Sanctum::actingAs($admin, ['admin']);

        $response = $this->postJson(self::CITIES_ENDPOINT, []);

        $response->assertStatus(406);
    }

    /**
     * Crea una ciudad validando departamento y coordenadas.
     */
    public function test_stores_city(): void
    {
        [$admin] = $this->createAdminApiUser();
        Sanctum::actingAs($admin, ['admin']);
        $departmentId = $this->createDepartment('Central');

        $response = $this->postJson(self::CITIES_ENDPOINT, [
            'nombre' => 'Villa Elisa',
            'departamento_id' => $departmentId,
            'latitud' => -25.367,
            'longitud' => -57.592,
        ]);

        $response->assertCreated();
        $this->assertDatabaseHas('ciudades', [
            'nombre' => 'Villa Elisa',
            'departamento_id' => $departmentId,
        ]);
    }

    /**
     * Crea un alias vinculado a una ciudad oficial existente.
     */
    public function test_stores_city_alias(): void
    {
        [$admin] = $this->createAdminApiUser();
        Sanctum::actingAs($admin, ['admin']);
        $departmentId = $this->createDepartment('San Pedro');
        $cityId = $this->createCity('San Estanislao', $departmentId);

        $response = $this->postJson(self::ALIASES_ENDPOINT, [
            'nombre' => 'Santaní',
            'ciudad_id' => $cityId,
        ]);

        $response->assertCreated();
        $this->assertDatabaseHas('ciudades_aliases', [
            'nombre' => 'Santaní',
            'ciudad_id' => $cityId,
        ]);
    }

    /**
     * Verifica la grilla de aliases con joins mínimos a ciudad y departamento.
     */
    public function test_lists_city_aliases(): void
    {
        [$admin] = $this->createAdminApiUser();
        Sanctum::actingAs($admin, ['admin']);
        $departmentId = $this->createDepartment('San Pedro');
        $cityId = $this->createCity('San Estanislao', $departmentId);

        DB::query()->from('ciudades_aliases')->insert([
            'ciudad_id' => $cityId,
            'nombre' => 'Santaní',
            'slug' => str_slug('Santaní'),
            'created_at' => now(),
            'updated_at' => now(),
        ]);

        $response = $this->getJson(self::ALIASES_ENDPOINT);

        $response->assertOk();
        $response->assertJsonFragment([
            'nombre' => 'Santaní',
            'ciudad' => 'San Estanislao',
            'departamento' => 'San Pedro',
        ]);
    }

    /**
     * Catálogo mínimo de departamentos para pruebas del CRUD.
     */
    private function createDepartment(string $name): int
    {
        return DB::query()->from('departamentos')->insertGetId([
            'nombre' => $name,
            'slug' => str_slug($name),
            'estado' => true,
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    /**
     * Inserta una ciudad oficial de prueba.
     */
    private function createCity(string $name, int $departmentId): int
    {
        return DB::query()->from('ciudades')->insertGetId([
            'nombre' => $name,
            'slug' => str_slug($name),
            'latitud' => -25.30,
            'longitud' => -57.60,
            'departamento_id' => $departmentId,
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }
}
