<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\ActivityLog;
use App\Models\Project;
use App\Models\Task;
use App\Models\TaskComment;
use App\Models\TaskFile;
use App\Models\TaskStatus;
use App\Models\User;
use App\Traits\LogsActivity;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\View\View;

class TaskController extends Controller
{
    use LogsActivity;

    public function show(Task $task): \Illuminate\Http\JsonResponse
    {
        $task->load(['project', 'module', 'status', 'assignees', 'watchers', 'subtasks', 'comments.user', 'files.uploader', 'timeLogs']);
        
        $activities = ActivityLog::where('metadata->task_id', $task->id)
            ->with('user')
            ->latest()
            ->take(15)
            ->get();

        return response()->json([
            'id' => $task->id,
            'title' => $task->title,
            'description' => $task->description,
            'priority' => $task->priority,
            'deadline' => $task->deadline?->format('Y-m-d'),
            'progress_percent' => $task->progress_percent,
            'estimated_hours' => $task->estimated_hours,
            'visibility' => $task->visibility,
            'tags' => $task->tags,
            'status' => $task->status,
            'project' => $task->project,
            'module' => $task->module,
            'assignees' => $task->assignees,
            'watchers' => $task->watchers,
            'subtasks' => $task->subtasks,
            'comments' => $task->comments,
            'files' => $task->files,
            'activities' => $activities,
            'active_timer' => $task->timeLogs()
                ->where('user_id', auth()->id())
                ->whereIn('status', ['running', 'paused'])
                ->latest()
                ->first(),
        ]);
    }

    public function index(Request $request): View
    {
        $query = Task::with(['project', 'module', 'status', 'assignees']);

        if ($request->filled('project_id')) {
            $query->where('project_id', $request->integer('project_id'));
        }
        if ($request->filled('status_id')) {
            $query->where('task_status_id', $request->integer('status_id'));
        }
        if ($request->filled('priority')) {
            $query->where('priority', $request->string('priority'));
        }
        if ($request->filled('employee_id')) {
            $query->whereHas('assignees', function($q) use ($request) {
                $q->where('users.id', $request->integer('employee_id'));
            });
        }
        if ($request->filled('date_start')) {
            $query->whereDate('deadline', '>=', $request->date('date_start'));
        }
        if ($request->filled('date_end')) {
            $query->whereDate('deadline', '<=', $request->date('date_end'));
        }
        if ($request->filled('q')) {
            $query->where('title', 'like', '%'.$request->string('q').'%');
        }

        return view('tasks.index', [
            'tasks' => $query->latest()->whereNull('parent_id')->paginate(12)->withQueryString(),
            'projects' => Project::orderBy('name')->get(),
            'statuses' => TaskStatus::orderBy('sort_order')->get(),
            'employees' => User::orderBy('name')->get(),
        ]);
    }

    public function kanban(Request $request): View
    {
        $statuses = TaskStatus::orderBy('sort_order')->get();
        $projectId = $request->integer('project_id');
        $employeeId = $request->integer('employee_id');
        
        $tasksQuery = Task::with(['project', 'assignees', 'status', 'timeLogs']);
        
        if ($projectId) {
            $tasksQuery->where('project_id', $projectId);
        }
        
        if ($employeeId) {
            $tasksQuery->whereHas('assignees', fn($q) => $q->where('users.id', $employeeId));
        }

        // Apply visibility logic
        if (!auth()->user()->hasRole('super_admin')) {
            $tasksQuery->where(function($q) {
                $q->where('visibility', 'public')
                  ->orWhereHas('assignees', fn($sq) => $sq->where('users.id', auth()->id()))
                  ->orWhereHas('watchers', fn($sq) => $sq->where('users.id', auth()->id()))
                  ->orWhere('created_by', auth()->id());
            });
        }
        
        $tasks = $tasksQuery->get()->groupBy('task_status_id');

        return view('tasks.kanban', [
            'statuses' => $statuses,
            'tasksByStatus' => $tasks,
            'projects' => Project::orderBy('name')->get(),
            'employees' => User::orderBy('name')->get(),
        ]);
    }

    public function timeline(Request $request, \App\Services\TimelineService $timelineService): View
    {
        $projectId = $request->integer('project_id');
        $employeeId = $request->integer('employee_id');
        
        $query = Task::with(['project', 'status', 'assignees', 'timeLogs'])->whereNotNull('deadline');
        
        if ($projectId) {
            $query->where('project_id', $projectId);
        }

        if ($employeeId) {
            $query->whereHas('assignees', fn($q) => $q->where('users.id', $employeeId));
        }

        // Apply visibility logic
        if (!auth()->user()->hasRole('super_admin')) {
            $query->where(function($q) {
                $q->where('visibility', 'public')
                  ->orWhereHas('assignees', fn($sq) => $sq->where('users.id', auth()->id()))
                  ->orWhereHas('watchers', fn($sq) => $sq->where('users.id', auth()->id()))
                  ->orWhere('created_by', auth()->id());
            });
        }

        $windowStart = now()->subDays(7)->startOfDay();
        $windowEnd = now()->addDays(23)->endOfDay();
        $tasks = $query->get();
        $lanes = $timelineService->calculateLanes($tasks, $windowStart, $windowEnd);

        return view('tasks.timeline', [
            'lanes' => $lanes,
            'projects' => Project::orderBy('name')->get(),
            'employees' => User::orderBy('name')->get(),
            'windowStart' => $windowStart,
            'windowEnd' => $windowEnd,
        ]);
    }

    public function create(): View
    {
        return view('admin.tasks.create', [
            'projects' => Project::with('modules')->orderBy('name')->get(),
            'statuses' => TaskStatus::orderBy('sort_order')->get(),
            'employees' => User::orderBy('name')->get(),
            'tasks' => Task::orderBy('title')->get(),
        ]);
    }

    public function store(Request $request): RedirectResponse|\Illuminate\Http\JsonResponse
    {
        $data = $request->validate([
            'project_id' => 'required|exists:projects,id',
            'project_module_id' => 'nullable|exists:project_modules,id',
            'task_status_id' => 'nullable|exists:task_statuses,id',
            'title' => 'required|string|max:255',
            'description' => 'nullable|string',
            'priority' => 'required|in:low,medium,high,critical',
            'deadline' => 'nullable|date',
            'estimated_hours' => 'nullable|integer|min:0',
            'visibility' => 'required|in:public,department,assigned',
            'tags' => 'nullable|array',
            'parent_id' => 'nullable|exists:tasks,id',
            'assignee_ids' => 'nullable|array',
            'assignee_ids.*' => 'exists:users,id',
            'watcher_ids' => 'nullable|array',
            'watcher_ids.*' => 'exists:users,id',
        ]);

        $task = Task::create([
            ...$data,
            'created_by' => auth()->id(),
        ]);

        if (isset($data['assignee_ids'])) $task->assignees()->sync($data['assignee_ids']);
        if (isset($data['watcher_ids'])) $task->watchers()->sync($data['watcher_ids']);

        $this->logActivity('create', 'task', 'Task created: ' . $task->title, ['task_id' => $task->id]);

        if ($request->wantsJson()) {
            return response()->json(['success' => true, 'task' => $task]);
        }

        return redirect()->route('tasks.index')->with('success', 'Task created successfully.');
    }

    public function storeSubtask(Request $request, Task $task): \Illuminate\Http\JsonResponse
    {
        $data = $request->validate(['title' => 'required|string|max:255']);
        $subtask = Task::create([
            'project_id' => $task->project_id,
            'project_module_id' => $task->project_module_id,
            'task_status_id' => 1, // To Do
            'parent_id' => $task->id,
            'title' => $data['title'],
            'priority' => $task->priority,
            'visibility' => $task->visibility,
            'created_by' => auth()->id(),
        ]);

        $this->logActivity('create_subtask', 'task', 'Subtask created: ' . $subtask->title, ['task_id' => $task->id]);
        return response()->json(['success' => true, 'subtask' => $subtask]);
    }
    public function edit(Task $task): View
    {
        return view('tasks.edit', [
            'task' => $task->load(['assignees', 'dependencies', 'files', 'comments.user']),
            'projects' => Project::with('modules')->orderBy('name')->get(),
            'statuses' => TaskStatus::orderBy('sort_order')->get(),
            'employees' => User::orderBy('name')->get(),
            'tasks' => Task::where('id', '!=', $task->id)->orderBy('title')->get(),
        ]);
    }

    public function update(Request $request, Task $task): RedirectResponse|\Illuminate\Http\JsonResponse
    {
        $data = $request->validate([
            'title' => 'sometimes|required|string|max:255',
            'description' => 'nullable|string',
            'task_status_id' => 'nullable|exists:task_statuses,id',
            'priority' => 'sometimes|required|in:low,medium,high,critical',
            'deadline' => 'nullable|date',
            'estimated_hours' => 'nullable|integer|min:0',
            'visibility' => 'nullable|in:public,department,assigned',
            'tags' => 'nullable|array',
            'assignee_ids' => 'nullable|array',
            'assignee_ids.*' => 'exists:users,id',
            'watcher_ids' => 'nullable|array',
            'watcher_ids.*' => 'exists:users,id',
        ]);

        $task->update($data);

        if (isset($data['assignee_ids'])) $task->assignees()->sync($data['assignee_ids']);
        if (isset($data['watcher_ids'])) $task->watchers()->sync($data['watcher_ids']);

        $this->logActivity('update', 'task', 'Task intelligence updated', ['task_id' => $task->id]);

        if ($request->wantsJson()) {
            return response()->json(['success' => true, 'task' => $task]);
        }

        return redirect()->route('tasks.index')->with('success', 'Task updated successfully.');
    }

    public function destroy(Task $task): RedirectResponse
    {
        $task->delete();
        $this->logActivity('delete', 'task', 'Task deleted', ['task_id' => $task->id]);

        return redirect()->route('tasks.index')->with('success', 'Task deleted successfully.');
    }

    public function addComment(Request $request, Task $task): RedirectResponse
    {
        $data = $request->validate(['comment' => 'required|string|max:2000']);

        TaskComment::create(['task_id' => $task->id, 'user_id' => auth()->id(), 'comment' => $data['comment']]);
        $this->logActivity('comment', 'task', 'Task comment added', ['task_id' => $task->id]);

        return back()->with('success', 'Comment added successfully.');
    }

    public function apiAddComment(Request $request, Task $task): \Illuminate\Http\JsonResponse
    {
        $data = $request->validate(['comment' => 'required|string|max:2000']);
        $comment = TaskComment::create(['task_id' => $task->id, 'user_id' => auth()->id(), 'comment' => $data['comment']]);
        $this->logActivity('comment', 'task', 'Task comment contributed', ['task_id' => $task->id]);
        return response()->json(['success' => true, 'comment' => $comment->load('user')]);
    }
    public function removeFile(TaskFile $file): RedirectResponse
    {
        Storage::disk('public')->delete($file->file_path);
        $taskId = $file->task_id;
        $file->delete();
        $this->logActivity('delete_file', 'task', 'Task file removed', ['task_id' => $taskId]);

        return back()->with('success', 'File removed successfully.');
    }

    public function updateStatus(Request $request, Task $task): RedirectResponse|\Illuminate\Http\JsonResponse
    {
        $data = $request->validate(['task_status_id' => 'required|exists:task_statuses,id']);
        $task->update(['task_status_id' => $data['task_status_id']]);
        
        // Auto-calculate progress if it has subtasks or is a subtask
        if ($task->parent_id) {
            $parent = $task->parent;
            $totalSub = $parent->subtasks()->count();
            if ($totalSub > 0) {
                $compSub = $parent->subtasks()->where('task_status_id', 3)->count(); // Assuming 3 is completed
                $parent->update(['progress_percent' => round(($compSub / $totalSub) * 100)]);
            }
        }

        $this->logActivity('status_change', 'task', 'Task status transitioned to: ' . $task->status->name, ['task_id' => $task->id]);

        if ($request->wantsJson()) {
            return response()->json(['success' => true, 'message' => 'Status updated and progress recalculated']);
        }

        return back()->with('success', 'Task status updated.');
    }
}
