<?php

declare(strict_types=1);

namespace Tests\Unit\Services;

use App\Services\TaskService;
use App\Services\LeadService;
use Tests\TestCase;

class TaskServiceTest extends TestCase
{
    private TaskService $taskService;
    private LeadService $leadService;
    private int $userId;
    private int $userId2;
    private int $eventId;

    protected function setUp(): void
    {
        parent::setUp();
        $this->taskService = new TaskService();
        $this->leadService = new LeadService();
        $this->userId = $this->createTestUser('gestor@test.com', 'comercial_manager', 'active');
        $this->userId2 = $this->createTestUser('gestor2@test.com', 'comercial_manager', 'active');
        $this->eventId = $this->createTestEvent('Feria Tasks', $this->userId);
    }

    private function createLead(): int
    {
        $lead = $this->leadService->createManual([
            'first_name' => 'Tarea', 'last_name' => 'Test', 'email' => 'tarea@test.com',
        ], $this->userId, $this->eventId);
        return $lead['id'];
    }

    public function testCreateTask(): void
    {
        $leadId = $this->createLead();
        $task = $this->taskService->createTask([
            'lead_id' => $leadId,
            'type' => 'llamada',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
            'scheduled_time' => '10:00',
            'notes' => 'Llamar para seguimiento',
            'assigned_to' => $this->userId,
        ], $this->userId);

        $this->assertEquals('llamada', $task['type']);
        $this->assertEquals('pendiente', $task['status']);
        $this->assertEquals($leadId, $task['lead_id']);
        $this->assertEquals($this->userId, $task['assigned_to']);
    }

    public function testCreateTaskWithoutLead(): void
    {
        $this->expectException(\RuntimeException::class);
        $this->taskService->createTask([
            'type' => 'llamada',
            'scheduled_date' => date('Y-m-d'),
        ], $this->userId);
    }

    public function testCreateTaskInvalidType(): void
    {
        $leadId = $this->createLead();

        $this->expectException(\RuntimeException::class);
        $this->taskService->createTask([
            'lead_id' => $leadId,
            'type' => 'tipo_invalido',
            'scheduled_date' => date('Y-m-d'),
        ], $this->userId);
    }

    public function testGetTasksByLead(): void
    {
        $leadId = $this->createLead();
        $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'llamada',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
        ], $this->userId);
        $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'correo',
            'scheduled_date' => date('Y-m-d', strtotime('+2 day')),
        ], $this->userId);

        $tasks = $this->taskService->getTasksByLead($leadId);
        $this->assertCount(2, $tasks);
    }

    public function testGetMyTasks(): void
    {
        $leadId = $this->createLead();
        $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'reunion',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
            'assigned_to' => $this->userId,
        ], $this->userId);

        $result = $this->taskService->getMyTasks($this->userId);
        $this->assertEquals(1, $result['total']);

        $result2 = $this->taskService->getMyTasks($this->userId2);
        $this->assertEquals(0, $result2['total']);
    }

    public function testGetMyTasksWithFilters(): void
    {
        $leadId = $this->createLead();
        $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'llamada',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
            'assigned_to' => $this->userId,
        ], $this->userId);
        $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'correo',
            'scheduled_date' => date('Y-m-d', strtotime('+2 day')),
            'assigned_to' => $this->userId,
        ], $this->userId);

        $result = $this->taskService->getMyTasks($this->userId, ['type' => 'llamada']);
        $this->assertEquals(1, $result['total']);
    }

    public function testUpdateTask(): void
    {
        $leadId = $this->createLead();
        $task = $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'seguimiento',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
        ], $this->userId);

        $updated = $this->taskService->updateTask($task['id'], [
            'type' => 'whatsapp',
            'notes' => 'Actualizada',
        ]);

        $this->assertEquals('whatsapp', $updated['type']);
        $this->assertEquals('Actualizada', $updated['notes']);
    }

    public function testUpdateTaskNotFound(): void
    {
        $this->expectException(\RuntimeException::class);
        $this->taskService->updateTask(9999, ['type' => 'llamada']);
    }

    public function testChangeStatusToCompleted(): void
    {
        $leadId = $this->createLead();
        $task = $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'otro',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
        ], $this->userId);

        $updated = $this->taskService->changeStatus($task['id'], 'completada');

        $this->assertEquals('completada', $updated['status']);
        $this->assertNotNull($updated['completed_at']);
    }

    public function testChangeStatusToCancelled(): void
    {
        $leadId = $this->createLead();
        $task = $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'seguimiento',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
        ], $this->userId);

        $updated = $this->taskService->changeStatus($task['id'], 'cancelada');

        $this->assertEquals('cancelada', $updated['status']);
        $this->assertNull($updated['completed_at']);
    }

    public function testChangeStatusInvalid(): void
    {
        $leadId = $this->createLead();
        $task = $this->taskService->createTask([
            'lead_id' => $leadId, 'type' => 'llamada',
            'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
        ], $this->userId);

        $this->expectException(\RuntimeException::class);
        $this->taskService->changeStatus($task['id'], 'estado_falso');
    }

    public function testAllTaskTypes(): void
    {
        $leadId = $this->createLead();
        foreach (['llamada', 'reunion', 'correo', 'whatsapp', 'seguimiento', 'otro'] as $type) {
            $task = $this->taskService->createTask([
                'lead_id' => $leadId, 'type' => $type,
                'scheduled_date' => date('Y-m-d', strtotime('+1 day')),
            ], $this->userId);
            $this->assertEquals($type, $task['type']);
        }
    }
}
