<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Requests\StoreTaskRequest;
use App\Http\Requests\UpdateTaskRequest;
use App\Http\Resources\TaskResource;
use App\Models\Task;
use App\Services\ActivityLogService;
use App\Services\NotificationService;
use App\Services\ProjectProgressService;
use App\Services\ResourceAccessService;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

class TaskController extends Controller
{
    public function __construct(
        protected ActivityLogService $activityLogService,
        protected NotificationService $notificationService,
        protected ProjectProgressService $projectProgressService,
        protected ResourceAccessService $resourceAccess,
    ) {}

    public function index(Request $request): JsonResponse
    {
        try {
            $query = $this->resourceAccess->tasks($request->user())
                ->with(['project', 'assignee', 'reporter'])
                ->withCount(['comments', 'files']);

            if ($request->filled('project_id')) {
                $query->where('project_id', $request->project_id);
            }
            if ($request->filled('assignee_id')) {
                $query->where('assignee_id', $request->assignee_id);
            }
            if ($request->filled('status')) {
                $query->where('status', $request->status);
            }
            if ($request->filled('priority')) {
                $query->where('priority', $request->priority);
            }
            if ($request->filled('search')) {
                $search = $request->search;
                $query->where('title', 'like', "%{$search}%");
            }

            $perPage = min((int) $request->input('per_page', 15), 100);
            $sortBy = in_array($request->input('sort_by'), ['id', 'title', 'status', 'priority', 'created_at', 'updated_at', 'due_date', 'sort_order'], true)
                ? $request->input('sort_by')
                : 'created_at';
            $sortDir = $request->input('sort_dir') === 'asc' ? 'asc' : 'desc';
            $tasks = $query->orderBy($sortBy, $sortDir)->paginate($perPage);

            return response()->json([
                'success' => true,
                'data' => TaskResource::collection($tasks),
                'meta' => [
                    'current_page' => $tasks->currentPage(),
                    'last_page' => $tasks->lastPage(),
                    'per_page' => $tasks->perPage(),
                    'total' => $tasks->total(),
                ],
                'message' => 'لیست وظایف',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت لیست وظایف',
            ], 500);
        }
    }

    public function show(Task $task): JsonResponse
    {
        try {
            $task->load(['project', 'assignee', 'reporter', 'checklists', 'subtasks', 'comments.user', 'files']);

            return response()->json([
                'success' => true,
                'data' => new TaskResource($task),
                'message' => 'اطلاعات وظیفه',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت اطلاعات وظیفه',
            ], 500);
        }
    }

    public function store(StoreTaskRequest $request): JsonResponse
    {
        try {
            $data = $request->validated();
            abort_unless(
                $this->resourceAccess->projects($request->user())->whereKey($data['project_id'])->exists(),
                403,
                'شما به پروژه انتخاب‌شده دسترسی ندارید.'
            );
            $data['reporter_id'] = $request->user()->id;
            $data['created_by'] = $request->user()->id;
            $task = Task::create($data);

            $this->projectProgressService->calculateProgress($task->project_id);

            $this->activityLogService->log(
                $request->user()->id,
                'create_task',
                "وظیفه {$task->title} ایجاد شد",
                'task',
                $task->id,
                $task->project_id,
                $task->id,
                ['task_title' => $task->title]
            );

            if ($task->assignee_id) {
                $this->notificationService->create(
                    $task->assignee_id,
                    'task_assigned',
                    [
                        'task_id' => $task->id,
                        'project_id' => $task->project_id,
                        'url' => '/kanban',
                        'notifiable_type' => 'App\\Models\\Task',
                        'notifiable_id' => $task->id,
                    ],
                    "وظیفه جدید {$task->title} به شما اختصاص داده شد"
                );
            }

            $task->load(['project', 'assignee', 'reporter']);

            return response()->json([
                'success' => true,
                'data' => new TaskResource($task),
                'message' => 'وظیفه با موفقیت ایجاد شد',
            ], 201);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در ایجاد وظیفه',
            ], 500);
        }
    }

    public function update(UpdateTaskRequest $request, Task $task): JsonResponse
    {
        try {
            $validated = $request->validated();
            if (isset($validated['project_id'])) {
                abort_unless(
                    $this->resourceAccess->projects($request->user())->whereKey($validated['project_id'])->exists(),
                    403,
                    'شما به پروژه انتخاب‌شده دسترسی ندارید.'
                );
            }
            $oldStatus = $task->status;
            $task->update($validated);

            if ($task->wasChanged('status')) {
                $this->activityLogService->log(
                    $request->user()->id,
                    'update_task_status',
                    "وضعیت وظیفه {$task->title} از {$oldStatus} به {$task->status} تغییر یافت",
                    'task',
                    $task->id,
                    $task->project_id,
                    $task->id,
                    ['old_status' => $oldStatus, 'new_status' => $task->status]
                );
            }

            $this->projectProgressService->calculateProgress($task->project_id);
            $task->load(['project', 'assignee', 'reporter']);

            return response()->json([
                'success' => true,
                'data' => new TaskResource($task->fresh()),
                'message' => 'وظیفه با موفقیت به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در به‌روزرسانی وظیفه',
            ], 500);
        }
    }

    public function destroy(Request $request, Task $task): JsonResponse
    {
        try {
            $projectId = $task->project_id;
            $taskId = $task->id;
            $taskTitle = $task->title;

            $this->activityLogService->log(
                $request->user()->id,
                'delete_task',
                "وظیفه {$taskTitle} حذف شد",
                'task',
                $taskId,
                $projectId,
                null,
                ['task_title' => $taskTitle]
            );

            $task->delete();
            $this->projectProgressService->calculateProgress($projectId);

            return response()->json([
                'success' => true,
                'message' => 'وظیفه با موفقیت حذف شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در حذف وظیفه',
            ], 500);
        }
    }

    public function updateStatus(Request $request, Task $task): JsonResponse
    {
        try {
            $request->validate(['status' => 'required|string']);

            $oldStatus = $task->status;
            $task->update(['status' => $request->status]);

            $this->projectProgressService->calculateProgress($task->project_id);

            $this->activityLogService->log(
                $request->user()->id,
                'update_task_status',
                "وضعیت وظیفه {$task->title} از {$oldStatus} به {$task->status} تغییر یافت",
                'task',
                $task->id,
                $task->project_id,
                $task->id,
                ['old_status' => $oldStatus, 'new_status' => $task->status]
            );

            if ($task->assignee_id) {
                $this->notificationService->create(
                    $task->assignee_id,
                    'task_status_changed',
                    ['task_id' => $task->id, 'status' => $task->status],
                    "وضعیت وظیفه {$task->title} به {$task->status} تغییر یافت"
                );
            }

            return response()->json([
                'success' => true,
                'data' => new TaskResource($task->fresh()->load(['project', 'assignee'])),
                'message' => 'وضعیت وظیفه به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در به‌روزرسانی وضعیت',
            ], 500);
        }
    }

    public function updateAssignee(Request $request, Task $task): JsonResponse
    {
        try {
            $request->validate(['assignee_id' => 'nullable|exists:users,id']);

            $oldAssigneeId = $task->assignee_id;
            $task->update(['assignee_id' => $request->assignee_id]);

            if ($request->assignee_id && $request->assignee_id != $oldAssigneeId) {
                $this->notificationService->create(
                    $request->assignee_id,
                    'task_assigned',
                    [
                        'task_id' => $task->id,
                        'project_id' => $task->project_id,
                        'url' => '/kanban',
                        'notifiable_type' => 'App\\Models\\Task',
                        'notifiable_id' => $task->id,
                    ],
                    "وظیفه {$task->title} به شما اختصاص داده شد"
                );
            }

            $this->activityLogService->log(
                $request->user()->id,
                'update_task_assignee',
                "مسئول وظیفه {$task->title} تغییر یافت",
                'task',
                $task->id,
                $task->project_id,
                $task->id,
                ['old_assignee' => $oldAssigneeId, 'new_assignee' => $request->assignee_id]
            );

            return response()->json([
                'success' => true,
                'data' => new TaskResource($task->fresh()->load(['project', 'assignee'])),
                'message' => 'مسئول وظیفه به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در به‌روزرسانی مسئول',
            ], 500);
        }
    }

    public function reorder(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'tasks' => 'required|array',
                'tasks.*.id' => 'required|exists:tasks,id',
                'tasks.*.sort_order' => 'required|integer',
            ]);

            foreach ($request->tasks as $item) {
                Task::where('id', $item['id'])->update(['sort_order' => $item['sort_order']]);
            }

            return response()->json([
                'success' => true,
                'message' => 'ترتیب وظایف به‌روزرسانی شد',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در مرتب‌سازی وظایف',
            ], 500);
        }
    }

    public function myTasks(Request $request): JsonResponse
    {
        try {
            $tasks = Task::with(['project', 'assignee'])
                ->where('assignee_id', $request->user()->id)
                ->where('status', '!=', 'done')
                ->orderBy('due_date')
                ->get();

            return response()->json([
                'success' => true,
                'data' => TaskResource::collection($tasks),
                'message' => 'وظایف من',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت وظایف من',
            ], 500);
        }
    }

    public function delayedTasks(): JsonResponse
    {
        try {
            $tasks = Task::with(['project', 'assignee'])
                ->where('due_date', '<', Carbon::now())
                ->where('status', '!=', 'done')
                ->orderBy('due_date')
                ->get();

            return response()->json([
                'success' => true,
                'data' => TaskResource::collection($tasks),
                'message' => 'وظایف عقب افتاده',
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'خطا در دریافت وظایف عقب افتاده',
            ], 500);
        }
    }
}
