<?php

namespace Tests\Feature;

use App\Enums\EventStatus;
use App\Enums\TransactionGateway;
use App\Models\Category;
use App\Models\Event;
use App\Models\Order;
use App\Models\Organizer;
use App\Models\Role;
use App\Models\TicketType;
use App\Models\User;
use App\Models\Venue;
use App\Services\OrderPaymentService;
use Database\Seeders\DemoCatalogSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Str;
use Tests\TestCase;

class OrderPaymentServiceTest extends TestCase
{
    use RefreshDatabase;

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

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

        $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' => 'Evento pago test',
            'slug' => 'evento-pago-test-'.Str::random(8),
            'description' => 'desc',
            'short_description' => 'short',
            'start_date' => $start,
            'end_date' => $start->copy()->addHours(2),
            'timezone' => 'America/Puerto_Rico',
            'status' => EventStatus::Published,
        ]);

        $ticket = TicketType::query()->create([
            'event_id' => $event->id,
            'name' => 'General',
            'price' => 25.00,
            'capacity' => 100,
            'quantity_sold' => 0,
            'is_active' => true,
        ]);

        Notification::fake();

        $order = Order::query()->create([
            'user_id' => null,
            'checkout_email' => 'a@example.com',
            'organizer_id' => $organizer->id,
            'total_amount' => 50.00,
            'platform_fee' => 5.49,
            'net_organizer_amount' => 44.51,
            'currency' => 'USD',
            'status' => 'pending',
        ]);

        $order->attendees()->createMany([
            [
                'ticket_type_id' => $ticket->id,
                'holder_name' => 'A',
                'holder_email' => 'a@example.com',
                'registration_data' => [],
            ],
            [
                'ticket_type_id' => $ticket->id,
                'holder_name' => 'B',
                'holder_email' => 'b@example.com',
                'registration_data' => [],
            ],
        ]);

        /** @var OrderPaymentService $svc */
        $svc = app(OrderPaymentService::class);

        $svc->completeOrder($order, TransactionGateway::Stripe, 'pi_123', ['ok' => true], amount: 55.49, currency: 'USD');

        $order->refresh();
        $this->assertNotNull($order->user_id);
        $this->assertDatabaseHas('users', [
            'email' => 'a@example.com',
        ]);
        $createdUser = User::query()->where('email', 'a@example.com')->first();
        $this->assertNotNull($createdUser);
        $this->assertTrue($createdUser->hasRole(Role::SLUG_CLIENTE));

        $this->assertDatabaseHas('orders', [
            'id' => $order->id,
            'status' => 'completed',
        ]);
        $this->assertDatabaseHas('transactions', [
            'order_id' => $order->id,
            'gateway' => 'stripe',
            'reference_id' => 'pi_123',
            'status' => 'succeeded',
        ]);
        $this->assertDatabaseHas('ticket_types', [
            'id' => $ticket->id,
            'quantity_sold' => 2,
        ]);

        // Idempotente: segunda llamada no debe incrementar otra vez.
        $svc->completeOrder($order, TransactionGateway::Stripe, 'pi_123', ['ok' => true], amount: 55.49, currency: 'USD');
        $this->assertDatabaseHas('ticket_types', [
            'id' => $ticket->id,
            'quantity_sold' => 2,
        ]);
    }
}
