<?php

namespace Tests\Feature;

use App\Models\Checkin;
use App\Models\PontoTuristico;
use App\Models\User;
use App\Models\UserRouteItem;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class CheckinTest extends TestCase
{
    use RefreshDatabase;

    private User $user;
    private PontoTuristico $ponto;

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

        $admin = User::factory()->create(['role' => 'admin']);
        $this->user = User::factory()->create(['user_type' => 'turista']);
        $this->ponto = PontoTuristico::create([
            'nome' => 'Ponto', 'tipo' => 'ponto_turistico', 'endereco' => 'R. X',
            'cidade' => 'Rio', 'estado' => 'RJ',
            'latitude' => -22.9519, 'longitude' => -43.2105,
            'status' => 'ativo', 'criado_por' => $admin->id,
        ]);
    }

    public function test_checkin_valido(): void
    {
        $response = $this->actingAs($this->user)->postJson('/api/v1/checkins', [
            'ponto_id'  => $this->ponto->id,
            'latitude'  => -22.9519,
            'longitude' => -43.2105,
        ]);

        $response->assertStatus(201)
            ->assertJsonPath('success', true)
            ->assertJsonStructure(['data' => ['id', 'ponto', 'latitude_usuario', 'longitude_usuario', 'data_hora']]);

        $this->assertDatabaseHas('checkins', [
            'user_id'  => $this->user->id,
            'ponto_id' => $this->ponto->id,
        ]);
    }

    public function test_checkin_gera_user_route_item_via_observer(): void
    {
        $this->actingAs($this->user)->postJson('/api/v1/checkins', [
            'ponto_id'  => $this->ponto->id,
            'latitude'  => -22.9519,
            'longitude' => -43.2105,
        ])->assertStatus(201);

        $this->assertDatabaseHas('user_route_items', [
            'user_id'  => $this->user->id,
            'ponto_id' => $this->ponto->id,
            'ordem'    => 1,
        ]);
    }

    public function test_checkin_distancia_maior_que_200m(): void
    {
        // São Paulo está a ~350km do ponto no Rio
        $response = $this->actingAs($this->user)->postJson('/api/v1/checkins', [
            'ponto_id'  => $this->ponto->id,
            'latitude'  => -23.5874,
            'longitude' => -46.6576,
        ]);

        $response->assertStatus(422)
            ->assertJson(['success' => false])
            ->assertJsonValidationErrors(['localizacao']);
    }

    public function test_checkin_duplicado_em_24h(): void
    {
        // Primeiro checkin
        Checkin::create([
            'user_id'          => $this->user->id,
            'ponto_id'         => $this->ponto->id,
            'latitude_usuario' => -22.9519,
            'longitude_usuario' => -43.2105,
            'data_hora'        => Carbon::now()->subHours(2),
        ]);

        // Segundo checkin (duplicado)
        $response = $this->actingAs($this->user)->postJson('/api/v1/checkins', [
            'ponto_id'  => $this->ponto->id,
            'latitude'  => -22.9519,
            'longitude' => -43.2105,
        ]);

        $response->assertStatus(422)
            ->assertJsonValidationErrors(['checkin']);
    }

    public function test_checkin_permite_apos_24h(): void
    {
        Checkin::create([
            'user_id'          => $this->user->id,
            'ponto_id'         => $this->ponto->id,
            'latitude_usuario' => -22.9519,
            'longitude_usuario' => -43.2105,
            'data_hora'        => Carbon::now()->subHours(25),
        ]);

        $response = $this->actingAs($this->user)->postJson('/api/v1/checkins', [
            'ponto_id'  => $this->ponto->id,
            'latitude'  => -22.9519,
            'longitude' => -43.2105,
        ]);

        $response->assertStatus(201);
    }

    public function test_listar_meus_checkins(): void
    {
        Checkin::create([
            'user_id' => $this->user->id, 'ponto_id' => $this->ponto->id,
            'latitude_usuario' => -22.95, 'longitude_usuario' => -43.21,
            'data_hora' => Carbon::now(),
        ]);

        $response = $this->actingAs($this->user)->getJson('/api/v1/checkins/meus');

        $response->assertOk()
            ->assertJsonCount(1, 'data.data');
    }

    public function test_meu_roteiro(): void
    {
        $checkin = Checkin::create([
            'user_id' => $this->user->id, 'ponto_id' => $this->ponto->id,
            'latitude_usuario' => -22.95, 'longitude_usuario' => -43.21,
            'data_hora' => Carbon::now(),
        ]);

        UserRouteItem::create([
            'user_id' => $this->user->id, 'ponto_id' => $this->ponto->id,
            'checkin_id' => $checkin->id, 'ordem' => 1, 'visitado_em' => $checkin->data_hora,
        ]);

        $response = $this->actingAs($this->user)->getJson('/api/v1/meu-roteiro');

        $response->assertOk()
            ->assertJsonStructure(['data' => ['itens', 'estatisticas']]);
    }

    public function test_checkin_nao_autenticado(): void
    {
        $this->postJson('/api/v1/checkins', [
            'ponto_id' => 1, 'latitude' => -22.95, 'longitude' => -43.21,
        ])->assertStatus(401);
    }
}
