<?php

declare(strict_types=1);

namespace Tests\Unit\Services;

use App\Models\Event;
use App\Services\EventService;
use Tests\TestCase;

class EventServiceTest extends TestCase
{
    private EventService $eventService;
    private Event $eventModel;
    private int $adminId;

    protected function setUp(): void
    {
        parent::setUp();
        $this->eventService = new EventService();
        $this->eventModel = new Event();
        $this->adminId = $this->createTestUser('admin@test.com', 'super_admin', 'active');
    }

    public function testCreateEvent(): void
    {
        $event = $this->eventService->createEvent([
            'name' => 'Feria Ganadera 2026',
            'description' => 'Evento anual de ganadería',
            'location' => 'Chihuahua',
            'start_date' => '2026-08-15',
            'end_date' => '2026-08-20',
        ]);

        $this->assertEquals('Feria Ganadera 2026', $event['name']);
        $this->assertEquals('Chihuahua', $event['location']);
        $this->assertEquals('active', $event['status']);
        $this->assertArrayHasKey('users', $event);
    }

    public function testCreateEventWithUsers(): void
    {
        $user1Id = $this->createTestUser('user1@test.com', 'comercial_manager', 'active');
        $user2Id = $this->createTestUser('user2@test.com', 'comercial_manager', 'active');

        $event = $this->eventService->createEvent([
            'name' => 'Congreso Avícola',
            'location' => 'Querétaro',
            'user_ids' => [$user1Id, $user2Id],
        ]);

        $this->assertCount(2, $event['users']);
    }

    public function testGetEvents(): void
    {
        $this->eventService->createEvent(['name' => 'Evento A', 'location' => 'Ciudad A']);
        $this->eventService->createEvent(['name' => 'Evento B', 'location' => 'Ciudad B']);

        $result = $this->eventService->getEvents();
        $this->assertGreaterThanOrEqual(2, $result['total']);
    }

    public function testGetEventsWithFilters(): void
    {
        $this->eventService->createEvent(['name' => 'Feria Porcina', 'location' => 'Jalisco']);
        $this->eventService->createEvent(['name' => 'Expo Bovina', 'location' => 'Sonora']);

        $result = $this->eventService->getEvents(['search' => 'Porcina']);
        $this->assertEquals(1, $result['total']);
    }

    public function testGetEventsPagination(): void
    {
        for ($i = 1; $i <= 5; $i++) {
            $this->eventService->createEvent(['name' => "Evento {$i}", 'location' => "Lugar {$i}"]);
        }

        $result = $this->eventService->getEvents([], 1, 3);
        $this->assertCount(3, $result['items']);
        $this->assertEquals(3, $result['per_page']);
    }

    public function testGetEvent(): void
    {
        $created = $this->eventService->createEvent(['name' => 'Evento Detalle', 'location' => 'Monterrey']);
        $event = $this->eventService->getEvent($created['id']);

        $this->assertEquals('Evento Detalle', $event['name']);
        $this->assertArrayHasKey('users', $event);
    }

    public function testGetEventNotFound(): void
    {
        $this->expectException(\RuntimeException::class);
        $this->eventService->getEvent(9999);
    }

    public function testUpdateEvent(): void
    {
        $created = $this->eventService->createEvent(['name' => 'Original', 'location' => 'CDMX']);

        $updated = $this->eventService->updateEvent($created['id'], [
            'name' => 'Actualizado',
            'description' => 'Nueva descripción',
        ]);

        $this->assertEquals('Actualizado', $updated['name']);
        $this->assertEquals('Nueva descripción', $updated['description']);
        $this->assertEquals('CDMX', $updated['location']);
    }

    public function testUpdateEventUsers(): void
    {
        $user1Id = $this->createTestUser('ev1@test.com', 'comercial_manager', 'active');
        $user2Id = $this->createTestUser('ev2@test.com', 'comercial_manager', 'active');

        $created = $this->eventService->createEvent([
            'name' => 'Con Usuarios',
            'user_ids' => [$user1Id],
        ]);

        $updated = $this->eventService->updateEvent($created['id'], [
            'user_ids' => [$user1Id, $user2Id],
        ]);

        $this->assertCount(2, $updated['users']);
    }

    public function testToggleStatus(): void
    {
        $created = $this->eventService->createEvent(['name' => 'Toggle Event', 'location' => 'Test']);

        $toggled = $this->eventService->toggleStatus($created['id']);
        $this->assertEquals('inactive', $toggled['status']);

        $toggledBack = $this->eventService->toggleStatus($created['id']);
        $this->assertEquals('active', $toggledBack['status']);
    }

    public function testGetUserEvents(): void
    {
        $userId = $this->createTestUser('gestor@test.com', 'comercial_manager', 'active');

        $event1 = $this->eventService->createEvent([
            'name' => 'Evento Asignado 1',
            'user_ids' => [$userId],
        ]);
        $event2 = $this->eventService->createEvent([
            'name' => 'Evento Asignado 2',
            'user_ids' => [$userId],
        ]);

        $this->eventService->createEvent([
            'name' => 'Evento No Asignado',
        ]);

        $userEvents = $this->eventService->getUserEvents($userId);
        $this->assertCount(2, $userEvents);
    }

    public function testSelectEvent(): void
    {
        $userId = $this->createTestUser('select@test.com', 'comercial_manager', 'active');

        $event = $this->eventService->createEvent([
            'name' => 'Evento Seleccionable',
            'user_ids' => [$userId],
        ]);

        $result = $this->eventService->selectEvent($userId, $event['id']);
        $this->assertEquals('Evento Seleccionable', $result['name']);

        $user = (new \App\Models\User())->findById($userId);
        $this->assertEquals($event['id'], $user['current_event_id']);
    }

    public function testSelectEventInactive(): void
    {
        $userId = $this->createTestUser('inactive@test.com', 'comercial_manager', 'active');

        $event = $this->eventService->createEvent([
            'name' => 'Evento Inactivo',
            'user_ids' => [$userId],
        ]);

        $this->eventService->toggleStatus($event['id']);

        $this->expectException(\RuntimeException::class);
        $this->eventService->selectEvent($userId, $event['id']);
    }

    public function testSelectEventNoAccess(): void
    {
        $userId = $this->createTestUser('sinacceso@test.com', 'comercial_manager', 'active');

        $event = $this->eventService->createEvent(['name' => 'Evento Privado']);

        $this->expectException(\RuntimeException::class);
        $this->eventService->selectEvent($userId, $event['id']);
    }

    public function testSelectEventNotFound(): void
    {
        $userId = $this->createTestUser('selectnf@test.com', 'comercial_manager', 'active');

        $this->expectException(\RuntimeException::class);
        $this->eventService->selectEvent($userId, 9999);
    }
}
