<?php

namespace Tests\Feature;

use App\Enums\EventStatus;
use App\Models\Category;
use App\Models\Event;
use App\Models\Organizer;
use App\Models\User;
use App\Models\Venue;
use Database\Seeders\DemoCatalogSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class VenueCrudTest extends TestCase
{
    use RefreshDatabase;

    protected function setUp(): void
    {
        parent::setUp();
        $this->seed(DemoCatalogSeeder::class);
    }

    public function test_cliente_no_accede_a_recintos(): void
    {
        $user = User::factory()->create();

        $this->actingAs($user)->get(route('dashboard.venues.index'))->assertForbidden();
    }

    public function test_organizador_puede_crear_y_editar_recinto_propio(): void
    {
        $org = User::factory()->organizador()->create();

        $this->actingAs($org)->get(route('dashboard.venues.index'))->assertOk();

        $this->actingAs($org)->post(route('dashboard.venues.store'), [
            'name' => 'Mi sede CRUD',
            'timezone' => 'America/Puerto_Rico',
            'city' => 'San Juan',
            'country' => 'PR',
        ])->assertRedirect();

        $venue = Venue::query()->where('name', 'Mi sede CRUD')->firstOrFail();
        $this->assertSame((int) $org->id, (int) $venue->catalog_submitted_by);

        $this->actingAs($org)->get(route('dashboard.venues.edit', $venue))->assertOk();

        $this->actingAs($org)->put(route('dashboard.venues.update', $venue), [
            'name' => 'Mi sede CRUD actualizada',
            'timezone' => 'America/Puerto_Rico',
            'city' => 'Bayamón',
            'country' => 'PR',
        ])->assertRedirect();

        $venue->refresh();
        $this->assertSame('Mi sede CRUD actualizada', $venue->name);
    }

    public function test_organizador_no_edita_recinto_de_otro(): void
    {
        $a = User::factory()->organizador()->create();
        $b = User::factory()->organizador()->create();

        $this->actingAs($a)->post(route('dashboard.venues.store'), [
            'name' => 'Sede de A',
            'timezone' => 'UTC',
        ])->assertRedirect();

        $venue = Venue::query()->where('name', 'Sede de A')->firstOrFail();

        $this->actingAs($b)->get(route('dashboard.venues.edit', $venue))->assertForbidden();
    }

    public function test_staff_edita_recinto_seed(): void
    {
        $venue = Venue::query()->firstOrFail();
        $admin = User::factory()->superAdmin()->create();

        $this->actingAs($admin)->get(route('dashboard.venues.edit', $venue))->assertOk();

        $this->actingAs($admin)->put(route('dashboard.venues.update', $venue), [
            'name' => $venue->name,
            'timezone' => $venue->timezone ?: 'America/Puerto_Rico',
            'city' => 'Test City',
        ])->assertRedirect();

        $venue->refresh();
        $this->assertSame('Test City', $venue->city);
    }

    public function test_staff_puede_archivar_recinto_aunque_tenga_eventos(): void
    {
        $org = User::factory()->organizador()->create();
        $organizer = Organizer::query()->create([
            'user_id' => $org->id,
            'stripe_account_id' => null,
        ]);

        $venue = Venue::query()->firstOrFail();
        $category = Category::query()->firstOrFail();

        $start = now()->addWeek();
        Event::query()->create([
            'organizer_id' => $organizer->id,
            'venue_id' => $venue->id,
            'category_id' => $category->id,
            'title' => 'Evento vinculado',
            'slug' => 'evento-vinculado-test-'.uniqid(),
            'description' => 'x',
            'short_description' => 'y',
            'start_date' => $start,
            'end_date' => $start->copy()->addHour(),
            'timezone' => 'America/Puerto_Rico',
            'status' => EventStatus::Draft,
            'metadata' => [],
        ]);

        $admin = User::factory()->administrador()->create();

        $this->actingAs($admin)->delete(route('dashboard.venues.destroy', $venue))
            ->assertRedirect(route('dashboard.venues.index'))
            ->assertSessionHas('success');

        $this->assertSoftDeleted($venue);
        $this->assertNotNull(Event::query()->where('venue_id', $venue->id)->first());
    }

    public function test_staff_elimina_recinto_sin_eventos(): void
    {
        $org = User::factory()->organizador()->create();
        $this->actingAs($org)->post(route('dashboard.venues.store'), [
            'name' => 'Sede huérfana',
            'timezone' => 'UTC',
        ])->assertRedirect();

        $venue = Venue::query()->where('name', 'Sede huérfana')->firstOrFail();
        $admin = User::factory()->superAdmin()->create();

        $this->actingAs($admin)->delete(route('dashboard.venues.destroy', $venue))
            ->assertRedirect(route('dashboard.venues.index'));

        $this->assertSoftDeleted($venue);
    }
}
