<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Helpers\Response;
use App\Services\TaskService;

class TaskController extends BaseController
{
    private TaskService $taskService;

    public function __construct($request)
    {
        parent::__construct($request);
        $this->taskService = new TaskService();
    }

    public function index(): void
    {
        $leadId = (int) $this->getRouteParam('id');
        $tasks = $this->taskService->getTasksByLead($leadId);
        Response::success($tasks, 'Tareas consultadas correctamente');
    }

    private function processAttachments(int $taskId): void
    {
        $singleFile = $this->request->uploadedFile('attachment');
        if ($singleFile && $singleFile['error'] === UPLOAD_ERR_OK) {
            $this->taskService->storeAttachments($taskId, $singleFile);
            return;
        }

        $multipleFiles = $this->request->uploadedFile('attachments');
        if ($multipleFiles && !empty($multipleFiles['name'][0])) {
            $this->taskService->storeAttachments($taskId, $multipleFiles);
        }
    }

    public function store(): void
    {
        $leadId = (int) $this->getRouteParam('id');
        $data = $this->request->body();
        $data['lead_id'] = $leadId;

        $validation = $this->validate($data, function ($v) {
            $v->required('type', 'Tipo de tarea');
            $v->required('scheduled_date', 'Fecha programada')
              ->date('scheduled_date', 'Fecha programada');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        try {
            $task = $this->taskService->createTask($data, $this->getAuthUserId());
            $this->processAttachments((int) $task['id']);
            $task = $this->taskService->getTaskById((int) $task['id']);
            Response::created($task, 'Tarea creada correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function storeAdmin(): void
    {
        $data = $this->request->body();

        $validation = $this->validate($data, function ($v) {
            $v->required('type', 'Tipo de tarea');
            $v->required('scheduled_date', 'Fecha programada')
              ->date('scheduled_date', 'Fecha programada');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        try {
            $task = $this->taskService->createTask($data, $this->getAuthUserId());
            $this->processAttachments((int) $task['id']);
            $task = $this->taskService->getTaskById((int) $task['id']);
            Response::created($task, 'Tarea creada correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function myTasks(): void
    {
        $filters = [
            'status' => $this->request->query('status'),
            'type' => $this->request->query('type'),
        ];

        $page = (int) ($this->request->query('page', 1));
        $perPage = (int) ($this->request->query('per_page', 50));

        $result = $this->taskService->getMyTasks($this->getAuthUserId(), $filters, $page, $perPage);

        Response::paginated(
            $result['items'],
            $result['total'],
            $result['page'],
            $result['per_page'],
            'Tareas consultadas correctamente'
        );
    }

    public function allTasks(): void
    {
        $filters = [
            'status' => $this->request->query('status'),
            'type' => $this->request->query('type'),
            'assigned_to' => $this->request->query('assigned_to'),
            'date_from' => $this->request->query('date_from'),
            'date_to' => $this->request->query('date_to'),
        ];

        $page = (int) ($this->request->query('page', 1));
        $perPage = (int) ($this->request->query('per_page', 50));

        $result = $this->taskService->getAllTasks($filters, $page, $perPage);

        Response::paginated(
            $result['items'],
            $result['total'],
            $result['page'],
            $result['per_page'],
            'Tareas consultadas correctamente'
        );
    }

    public function types(): void
    {
        try {
            $types = $this->taskService->getTaskTypes();
            Response::success($types, 'Tipos consultados correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function renameType(): void
    {
        $data = $this->request->body();

        if (empty($data['old_type'])) {
            Response::error('El tipo original es obligatorio', 422);
        }
        if (empty($data['new_type'])) {
            Response::error('El nuevo tipo es obligatorio', 422);
        }

        try {
            $this->taskService->renameTaskType($data['old_type'], $data['new_type']);
            Response::success(null, 'Tipo renombrado correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function deleteType(): void
    {
        $data = $this->request->body();

        if (empty($data['type'])) {
            Response::error('El tipo es obligatorio', 422);
        }

        try {
            $this->taskService->deleteTaskType($data['type']);
            Response::success(null, 'Tipo eliminado correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function update(): void
    {
        $id = (int) $this->getRouteParam('id');
        $data = $this->request->body();

        try {
            $task = $this->taskService->updateTask($id, $data);
            $this->processAttachments($id);
            $task = $this->taskService->getTaskById($id);
            Response::success($task, 'Tarea actualizada correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function destroyAttachment(): void
    {
        $id = (int) $this->getRouteParam('id');
        $attachmentId = (int) $this->getRouteParam('attachmentId');

        try {
            $this->taskService->deleteAttachmentFile($attachmentId);
            Response::success([], 'Archivo eliminado correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function changeStatus(): void
    {
        $id = (int) $this->getRouteParam('id');
        $data = $this->request->body();

        $validation = $this->validate($data, function ($v) {
            $v->required('status', 'Estado')
              ->inValues('status', ['pendiente', 'completada', 'cancelada'], 'Estado');
        });

        if ($validation->fails()) {
            Response::error($validation->firstError(), 422);
        }

        try {
            $task = $this->taskService->changeStatus($id, $data['status']);
            Response::success($task, 'Estado de tarea actualizado correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }

    public function destroy(): void
    {
        $id = (int) $this->getRouteParam('id');

        try {
            $this->taskService->deleteTask($id, $this->getAuthUserId(), $this->getAuthUserRole());
            Response::success([], 'Tarea eliminada correctamente');
        } catch (\RuntimeException $e) {
            Response::error($e->getMessage(), $e->getCode() ?: 400);
        }
    }
}
