<?php

use App\Enums\ParticipateStatus;
use App\Models\Hunts;
use App\Models\HuntSteps;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('registers a participant without starting the hunt', function () {
    $user = User::factory()->create();
    $hunt = Hunts::withoutSyncingToSearch(fn () => Hunts::factory()->create());

    $response = $this
        ->actingAs($user, 'sanctum')
        ->postJson("/api/hunts/{$hunt->id}/participate");

    $response
        ->assertOk()
        ->assertJsonPath('participation_status.current_step_number', 0)
        ->assertJsonPath('participation_status.status', ParticipateStatus::Registered->value);

    $this->assertDatabaseHas('hunt_participants', [
        'user_id' => $user->id,
        'hunt_id' => $hunt->id,
        'current_step_number' => 0,
        'status' => ParticipateStatus::Registered->value,
    ]);
});

it('starts a joined hunt only when the user is inside the start radius', function () {
    $user = User::factory()->create();
    $hunt = Hunts::withoutSyncingToSearch(fn () => Hunts::factory()->create([
        'latitude' => 44.837789,
        'longitude' => -0.57918,
        'start_radius_m' => 40,
    ]));
    $step = HuntSteps::factory()->create([
        'hunt_id' => $hunt->id,
        'step_number' => 1,
        'latitude' => 44.838,
        'longitude' => -0.579,
    ]);

    $hunt->participants()->attach($user->id, [
        'current_step_number' => 0,
        'status' => ParticipateStatus::Registered->value,
    ]);

    $tooFarResponse = $this
        ->actingAs($user, 'sanctum')
        ->postJson("/api/hunts/{$hunt->id}/start", [
            'latitude' => 44.85,
            'longitude' => -0.59,
        ]);

    $tooFarResponse->assertBadRequest();

    $response = $this
        ->actingAs($user, 'sanctum')
        ->postJson("/api/hunts/{$hunt->id}/start", [
            'latitude' => 44.837789,
            'longitude' => -0.57918,
        ]);

    $response
        ->assertOk()
        ->assertJsonPath('participation_status.current_step_number', 1)
        ->assertJsonPath('participation_status.status', ParticipateStatus::InProgress->value)
        ->assertJsonPath('current_step.id', $step->id)
        ->assertJsonPath('current_step.step_number', 1);
});

it('does not expose a current step before the hunt is started', function () {
    $user = User::factory()->create();
    $hunt = Hunts::withoutSyncingToSearch(fn () => Hunts::factory()->create());

    $hunt->participants()->attach($user->id, [
        'current_step_number' => 0,
        'status' => ParticipateStatus::Registered->value,
    ]);

    $response = $this
        ->actingAs($user, 'sanctum')
        ->getJson("/api/hunts/{$hunt->id}/current-step");

    $response
        ->assertStatus(409)
        ->assertJsonPath('participation_status.status', ParticipateStatus::Registered->value);
});

it('validates the current step and returns the next step target', function () {
    $user = User::factory()->create();
    $hunt = Hunts::withoutSyncingToSearch(fn () => Hunts::factory()->create());
    $firstStep = HuntSteps::factory()->create([
        'hunt_id' => $hunt->id,
        'step_number' => 1,
        'title' => 'First clue',
        'hint_text' => 'Go to the next chest',
        'latitude' => 44.837789,
        'longitude' => -0.57918,
        'radius_m' => 30,
    ]);
    $nextStep = HuntSteps::factory()->create([
        'hunt_id' => $hunt->id,
        'step_number' => 2,
        'latitude' => 44.838,
        'longitude' => -0.579,
    ]);

    $hunt->participants()->attach($user->id, [
        'current_step_number' => 1,
        'status' => ParticipateStatus::InProgress->value,
    ]);

    $response = $this
        ->actingAs($user, 'sanctum')
        ->postJson("/api/hunts/{$hunt->id}/steps/{$firstStep->id}/validate", [
            'latitude' => 44.837789,
            'longitude' => -0.57918,
        ]);

    $response
        ->assertOk()
        ->assertJsonPath('revealed_hint.hint_text', 'Go to the next chest')
        ->assertJsonPath('next_step.id', $nextStep->id)
        ->assertJsonPath('next_step.step_number', 2);

    $this->assertDatabaseHas('hunt_participants', [
        'user_id' => $user->id,
        'hunt_id' => $hunt->id,
        'current_step_number' => 2,
        'status' => ParticipateStatus::InProgress->value,
    ]);
});
