<?php

namespace App\Services;

use App\Models\ActivityLog;
use App\Models\Project;
use App\Models\Sprint;
use App\Models\Task;
use App\Models\User;
use Carbon\Carbon;

class ReportService
{
    protected function applyDateFilters($query, $filters, $dateField = 'created_at')
    {
        if (! empty($filters['date_from'])) {
            $query->where($dateField, '>=', $filters['date_from']);
        }
        if (! empty($filters['date_to'])) {
            $query->where($dateField, '<=', $filters['date_to']);
        }

        return $query;
    }

    public function projectStatus($filters = [])
    {
        $query = Project::query();

        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }
        if (! empty($filters['project_id'])) {
            $query->where('id', $filters['project_id']);
        }

        $projects = $query->get();
        $grouped = $projects->groupBy('status');

        return $grouped->map(fn ($items, $status) => [
            'status' => $status === 'planning' ? 'برنامه‌ریزی' : ($status === 'in_progress' ? 'در حال انجام' : ($status === 'done' ? 'تکمیل شده' : ($status === 'on_hold' ? 'متوقف' : $status))),
            'count' => $items->count(),
            'label' => $status,
            'value' => $items->count(),
        ])->values();
    }

    public function delayedTasks($filters = [])
    {
        $query = Task::with(['project:id,title', 'assignee:id,name'])
            ->whereDate('due_date', '<', Carbon::today())
            ->where('status', '!=', 'done');

        $query = $this->applyDateFilters($query, $filters, 'due_date');

        if (! empty($filters['project_id'])) {
            $query->where('project_id', $filters['project_id']);
        }
        if (! empty($filters['user_id'])) {
            $query->where('assignee_id', $filters['user_id']);
        }
        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        return $query->orderBy('due_date')->get()->map(fn ($t) => [
            'id' => $t->id,
            'title' => $t->title,
            'project' => ['title' => $t->project?->title],
            'project_name' => $t->project?->title,
            'assignee' => ['name' => $t->assignee?->name],
            'assignee_name' => $t->assignee?->name,
            'due_date' => $t->due_date?->format('Y-m-d'),
            'delay_days' => abs(Carbon::today()->diffInDays($t->due_date, false)),
            'days_delayed' => abs(Carbon::today()->diffInDays($t->due_date, false)),
            'priority' => $t->priority,
        ]);
    }

    public function teamPerformance($filters = [])
    {
        $query = User::with(['tasks' => function ($q) use ($filters) {
            if (! empty($filters['date_from'])) {
                $q->where('created_at', '>=', $filters['date_from']);
            }
            if (! empty($filters['date_to'])) {
                $q->where('created_at', '<=', $filters['date_to']);
            }
        }]);

        if (! empty($filters['user_id'])) {
            $query->where('id', $filters['user_id']);
        }

        $users = $query->get();

        return $users->map(function ($user) {
            $totalTasks = $user->tasks->count();
            $completedTasks = $user->tasks->where('status', 'done')->count();
            $delayedTasks = $user->tasks->where('due_date', '<', Carbon::now())->where('status', '!=', 'done')->count();
            $inProgress = $user->tasks->whereNotIn('status', ['done', 'canceled'])->count();

            return [
                'name' => $user->name,
                'completed' => $completedTasks,
                'in_progress' => $inProgress,
                'delayed' => $delayedTasks,
                'total' => $totalTasks,
            ];
        });
    }

    public function workload($filters = [])
    {
        $query = User::query();

        if (! empty($filters['user_id'])) {
            $query->where('id', $filters['user_id']);
        }

        $users = $query->get();

        $allActiveTasks = Task::where('status', '!=', 'done')->count();
        $maxTasks = max($allActiveTasks, 1);

        return $users->map(function ($user) use ($maxTasks) {
            $activeTasks = Task::where('assignee_id', $user->id)->where('status', '!=', 'done')->count();
            $loadPercent = min(round(($activeTasks / $maxTasks) * 100), 100);

            return [
                'user_id' => $user->id,
                'name' => $user->name,
                'tasks_count' => $activeTasks,
                'total' => $activeTasks,
                'load_percent' => $loadPercent,
                'load' => $loadPercent,
            ];
        });
    }

    public function sprintProgress($filters = [])
    {
        $query = Sprint::with(['project:id,title', 'tasks']);

        if (! empty($filters['project_id'])) {
            $query->where('project_id', $filters['project_id']);
        }
        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        $sprints = $query->get();

        return $sprints->map(function ($sprint) {
            $totalTasks = $sprint->tasks->count();
            $completedTasks = $sprint->tasks->where('status', 'done')->count();

            return [
                'id' => $sprint->id,
                'title' => $sprint->title,
                'project' => $sprint->project?->title,
                'start_date' => $sprint->start_date,
                'end_date' => $sprint->end_date,
                'status' => $sprint->status,
                'total_tasks' => $totalTasks,
                'completed_tasks' => $completedTasks,
                'progress' => $totalTasks > 0 ? round(($completedTasks / $totalTasks) * 100, 2) : 0,
            ];
        });
    }

    public function timeEstimate($filters = [])
    {
        $query = Task::with('project');
        $query = $this->applyDateFilters($query, $filters);

        if (! empty($filters['project_id'])) {
            $query->where('project_id', $filters['project_id']);
        }
        if (! empty($filters['user_id'])) {
            $query->where('assignee_id', $filters['user_id']);
        }
        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }

        $tasks = $query->get();

        return $tasks->map(function ($task) {
            $diff = ($task->estimated_time ?? 0) - ($task->actual_time ?? 0);

            return [
                'id' => $task->id,
                'title' => $task->title,
                'project' => ['title' => $task->project?->title ?? '—'],
                'estimated' => $task->estimated_time,
                'estimated_time' => $task->estimated_time,
                'actual' => $task->actual_time,
                'actual_time' => $task->actual_time,
                'diff' => $diff,
                'difference' => $diff,
                'status' => $task->status,
            ];
        });
    }

    public function recentActivities($filters = [])
    {
        $query = ActivityLog::with('user');
        $query = $this->applyDateFilters($query, $filters);

        if (! empty($filters['project_id'])) {
            $query->where('project_id', $filters['project_id']);
        }
        if (! empty($filters['user_id'])) {
            $query->where('user_id', $filters['user_id']);
        }
        if (! empty($filters['action'])) {
            $query->where('action', $filters['action']);
        }

        return $query->orderBy('created_at', 'desc')->limit(50)->get()->map(fn ($log) => [
            'id' => $log->id,
            'description' => $log->description,
            'user' => $log->user?->name ?? '?',
            'user_name' => $log->user?->name ?? '?',
            'created_at' => $log->created_at?->toDateTimeString(),
            'time_ago' => $log->created_at?->diffForHumans(),
        ]);
    }

    public function riskyProjects($filters = [])
    {
        $query = Project::whereIn('risk_level', ['high', 'critical'])->where('is_archived', false);

        if (! empty($filters['status'])) {
            $query->where('status', $filters['status']);
        }
        if (! empty($filters['project_id'])) {
            $query->where('id', $filters['project_id']);
        }

        return $query->with('projectManager:id,name')->get()->map(fn ($p) => [
            'id' => $p->id,
            'title' => $p->title,
            'risk_level' => $p->risk_level,
            'progress' => $p->progress,
            'delayed_tasks' => Task::where('project_id', $p->id)->where('due_date', '<', Carbon::now())->where('status', '!=', 'done')->count(),
        ]);
    }
}
