<?php

namespace Tests\Feature;

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

/**
 * Cobertura del flujo público de compra:
 *
 *   GET  /eventos/{slug}                      → renderiza selector de tickets.
 *   POST /eventos/{slug}/checkout             → crea Order pending + Attendees con security_code.
 *   GET  /eventos/{slug}/checkout/{order}/confirmacion → muestra resumen.
 */
class PublicCheckoutTest extends TestCase
{
    use RefreshDatabase;

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

    public function test_pagina_publica_muestra_la_estructura_de_selector_de_tickets(): void
    {
        $event = $this->makePublishedEventWithTickets(qty: 1);

        $response = $this->get(route('landing.event.show', ['event' => $event->slug]));

        $response->assertOk();
        $response->assertSeeText(__('Entradas'));
        $response->assertSeeText(__('Obtener Entradas'));
        $response->assertSee('rt-tickets-list', escape: false);
        $response->assertSee('rt-tickets-buy-btn', escape: false);
        $response->assertSee('rt-checkout-swal-wrap', escape: false);
    }

    public function test_post_checkout_crea_order_pending_con_attendees_y_fee(): void
    {
        $event = $this->makePublishedEventWithTickets(qty: 1);
        /** @var TicketType $ticket */
        $ticket = $event->ticketTypes()->first();

        $response = $this->post(route('landing.event.checkout', ['event' => $event->slug]), [
            'checkout_email' => 'juan@example.com',
            'attendees' => [
                $ticket->id => [
                    [
                        'holder_name' => 'Juan Pérez',
                        'holder_email' => 'juan@example.com',
                        'meta' => [
                            'shirt' => 'M',
                        ],
                    ],
                    [
                        'holder_name' => 'Ana Ríos',
                        'holder_email' => 'ana@example.com',
                        'meta' => [
                            'shirt' => 'L',
                        ],
                    ],
                ],
            ],
        ]);

        $response->assertRedirect();

        $order = Order::query()->latest('id')->first();
        $this->assertNotNull($order);
        $this->assertSame('pending', $order->status->value);
        // Base 25 × 2 = 50. Por entrada: 2.99 + (25 × 5%) = 4.24 → fee total 8.48 → total cobrado 58.48
        $this->assertEquals(58.48, (float) $order->total_amount);
        $this->assertEquals(8.48, (float) $order->platform_fee);
        $this->assertEquals(50.00, (float) $order->net_organizer_amount);
        $this->assertSame(2, $order->attendees()->count());
        $this->assertNotEmpty($order->attendees()->first()->security_code);
        $this->assertSame('juan@example.com', $order->checkout_email);
    }

    public function test_checkout_falla_si_falta_un_custom_field_requerido(): void
    {
        $event = $this->makePublishedEventWithTickets(qty: 1);
        /** @var TicketType $ticket */
        $ticket = $event->ticketTypes()->first();

        $response = $this->post(route('landing.event.checkout', ['event' => $event->slug]), [
            'checkout_email' => 'juan@example.com',
            'attendees' => [
                $ticket->id => [
                    [
                        'holder_name' => 'Juan Pérez',
                        'holder_email' => 'juan@example.com',
                        'meta' => [], // falta 'shirt' que es requerido
                    ],
                ],
            ],
        ]);

        $response->assertSessionHasErrors();
        $this->assertSame(0, Order::query()->count());
    }

    public function test_checkout_rechaza_cantidad_mayor_a_la_disponible(): void
    {
        $event = $this->makePublishedEventWithTickets(qty: 1, capacity: 1);
        /** @var TicketType $ticket */
        $ticket = $event->ticketTypes()->first();

        $payload = [
            'checkout_email' => 'a@example.com',
            'attendees' => [
                $ticket->id => [
                    [
                        'holder_name' => 'A',
                        'holder_email' => 'a@example.com',
                        'meta' => ['shirt' => 'M'],
                    ],
                    [
                        'holder_name' => 'B',
                        'holder_email' => 'b@example.com',
                        'meta' => ['shirt' => 'M'],
                    ],
                ],
            ],
        ];

        $response = $this->post(route('landing.event.checkout', ['event' => $event->slug]), $payload);

        $response->assertSessionHasErrors();
        $this->assertSame(0, Order::query()->count());
    }

    public function test_evento_no_publicado_no_es_accesible(): void
    {
        $event = $this->makePublishedEventWithTickets(qty: 1);
        $event->update(['status' => EventStatus::Draft]);

        $this->get(route('landing.event.show', ['event' => $event->slug]))->assertNotFound();
    }

    private function makePublishedEventWithTickets(int $qty = 1, int $capacity = 100): Event
    {
        $orgUser = User::factory()->organizador()->create();
        $organizer = Organizer::query()->create(['user_id' => $orgUser->id, 'stripe_account_id' => null]);

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

        $start = now()->addMonth()->startOfHour();
        $event = Event::query()->create([
            'organizer_id' => $organizer->id,
            'venue_id' => $venue->id,
            'category_id' => $category->id,
            'title' => 'Carrera Pública Test '.uniqid('', false),
            'slug' => 'carrera-publica-test-'.Str::random(8),
            'description' => 'Descripción del evento',
            'short_description' => 'Resumen',
            'start_date' => $start,
            'end_date' => $start->copy()->addHours(2),
            'timezone' => 'America/Puerto_Rico',
            'status' => EventStatus::Published,
        ]);

        for ($i = 0; $i < $qty; $i++) {
            $ticket = TicketType::query()->create([
                'event_id' => $event->id,
                'name' => '5K General',
                'description' => 'Inscripción 5K',
                'price' => 25.00,
                'currency' => 'USD',
                'capacity_strategy' => 'per_ticket',
                'capacity' => $capacity,
                'iac' => 'required',
                'ticket_kind' => 'standard',
                'is_active' => true,
            ]);

            CustomField::query()->create([
                'ticket_type_id' => $ticket->id,
                'label' => 'Talla camisa',
                'slug' => 'shirt',
                'type' => 'select',
                'options' => ['S', 'M', 'L', 'XL'],
                'required' => true,
                'sort_order' => 1,
            ]);
        }

        return $event->fresh(['ticketTypes.customFields']);
    }
}
