<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Http\Resources\CommentResource;
use App\Http\Resources\FileResource;
use App\Models\ActivityLog;
use App\Models\Comment;
use App\Models\File;
use App\Models\Notification;
use App\Models\Project;
use App\Models\Sprint;
use App\Models\Task;
use App\Models\User;
use App\Services\ProjectProgressService;
use App\Services\ResourceAccessService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;

class PwaController extends Controller
{
    public function __construct(
        protected ProjectProgressService $projectProgressService,
        protected ResourceAccessService $resourceAccess,
    ) {}

    public function profile(Request $request): JsonResponse
    {
        $user = $request->user()->loadMissing(['roles.permissions', 'dept', 'departments']);
        $permissions = $user->roles
            ->flatMap(fn ($role) => $role->permissions->pluck('name'))
            ->unique()
            ->values();

        return response()->json([
            'success' => true,
            'data' => [
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'email' => $user->email,
                    'phone' => $user->phone,
                    'job_title' => $user->job_title,
                    'department' => $user->dept?->name ?: $user->department,
                    'status' => $user->status ?: 'active',
                    'avatar' => $user->avatar,
                    'avatar_url' => $user->avatar ? asset('storage/'.$user->avatar) : null,
                    'roles' => $user->roles->map(fn ($role) => [
                        'id' => $role->id,
                        'name' => $role->name,
                        'display_name' => $role->display_name,
                    ])->values(),
                    'primary_role' => $user->roles->first()?->display_name ?: $user->roles->first()?->name,
                    'departments' => $user->departments->map(fn ($department) => [
                        'id' => $department->id,
                        'name' => $department->name,
                        'role_in_team' => $department->pivot?->role_in_team,
                        'is_primary' => (bool) $department->pivot?->is_primary,
                    ])->values(),
                ],
                'access_summary' => $this->profileAccessSummary($permissions, $user),
                'capabilities' => [
                    'can_change_password' => true,
                    'can_update_profile' => true,
                    'can_update_avatar' => true,
                    'push_backend_ready' => false,
                ],
            ],
            'message' => 'پروفایل موبایل',
        ]);
    }

    public function projects(Request $request): JsonResponse
    {
        $user = $request->user()->loadMissing(['roles.permissions']);
        $query = $this->visibleProjectsQuery($user)
            ->with(['projectManager:id,name,job_title,avatar', 'members:id,name,job_title,avatar'])
            ->withCount([
                'tasks',
                'tasks as done_tasks_count' => fn ($taskQuery) => $taskQuery->where('status', 'done'),
                'tasks as overdue_tasks_count' => fn ($taskQuery) => $taskQuery
                    ->whereDate('due_date', '<', now()->toDateString())
                    ->whereNotIn('status', ['done', 'canceled', 'cancelled']),
            ]);

        $filter = $request->input('filter', 'all');
        match ($filter) {
            'active' => $query->where('status', 'active'),
            'waiting' => $query->whereIn('status', ['waiting', 'pending']),
            'completed' => $query->whereIn('status', ['completed', 'done']),
            'delayed' => $query->whereHas('tasks', fn ($taskQuery) => $taskQuery
                ->whereDate('due_date', '<', now()->toDateString())
                ->whereNotIn('status', ['done', 'canceled', 'cancelled'])),
            'mine' => $query->where(function ($scopeQuery) use ($user) {
                $scopeQuery->where('project_manager_id', $user->id)
                    ->orWhereHas('members', fn ($memberQuery) => $memberQuery->where('users.id', $user->id));
            }),
            default => null,
        };

        if ($request->filled('search')) {
            $search = trim($request->input('search'));
            $query->where('title', 'like', "%{$search}%");
        }

        $projects = $query
            ->where(function ($scopeQuery) {
                $scopeQuery->where('is_archived', false)->orWhereNull('is_archived');
            })
            ->orderByRaw('case when end_date is null then 1 else 0 end')
            ->orderBy('end_date')
            ->latest()
            ->paginate(min((int) $request->input('per_page', 20), 50));

        return response()->json([
            'success' => true,
            'data' => collect($projects->items())->map(fn (Project $project) => $this->projectCard($project))->values(),
            'meta' => [
                'current_page' => $projects->currentPage(),
                'last_page' => $projects->lastPage(),
                'per_page' => $projects->perPage(),
                'total' => $projects->total(),
            ],
            'message' => 'پروژه‌های موبایل',
        ]);
    }

    public function projectDetail(Request $request, Project $project): JsonResponse
    {
        $this->abortUnlessProjectVisible($request, $project);
        $today = now()->toDateString();

        $project->load([
            'projectManager:id,name,job_title,avatar',
            'members:id,name,job_title,avatar',
            'tasks' => fn ($taskQuery) => $taskQuery
                ->with(['assignee:id,name,job_title'])
                ->orderByRaw("case priority when 'urgent' then 0 when 'high' then 1 when 'medium' then 2 else 3 end")
                ->orderByRaw('case when due_date is null then 1 else 0 end')
                ->orderBy('due_date')
                ->limit(8),
        ])->loadCount([
            'tasks',
            'tasks as done_tasks_count' => fn ($taskQuery) => $taskQuery->where('status', 'done'),
            'tasks as overdue_tasks_count' => fn ($taskQuery) => $taskQuery
                ->whereDate('due_date', '<', $today)
                ->whereNotIn('status', ['done', 'canceled', 'cancelled']),
            'tasks as today_tasks_count' => fn ($taskQuery) => $taskQuery->whereDate('due_date', $today),
            'members',
        ]);

        $activities = ActivityLog::query()
            ->where('project_id', $project->id)
            ->latest()
            ->limit(6)
            ->get(['id', 'action', 'description', 'created_at'])
            ->map(fn (ActivityLog $activity) => [
                'id' => $activity->id,
                'action' => $activity->action,
                'description' => $activity->description,
                'created_at' => $activity->created_at,
            ]);

        return response()->json([
            'success' => true,
            'data' => array_merge($this->projectCard($project), [
                'description' => $project->description,
                'members_count' => $project->members_count,
                'today_tasks_count' => $project->today_tasks_count,
                'tasks' => $project->tasks->map(fn (Task $task) => $this->taskCard($task))->values(),
                'members' => $project->members->map(fn (User $member) => [
                    'id' => $member->id,
                    'name' => $member->name,
                    'job_title' => $member->job_title,
                    'avatar_url' => $member->avatar ? asset('storage/'.$member->avatar) : null,
                    'role_in_project' => $member->pivot?->role_in_project,
                ])->values(),
                'activities' => $activities,
            ]),
            'message' => 'جزئیات پروژه',
        ]);
    }

    public function updateProjectStatus(Request $request, Project $project): JsonResponse
    {
        $this->abortUnlessProjectVisible($request, $project);

        $data = $request->validate([
            'status' => ['required', Rule::in(['active', 'waiting', 'pending', 'paused', 'completed', 'done'])],
        ], [
            'status.required' => 'انتخاب وضعیت پروژه الزامی است.',
            'status.in' => 'وضعیت انتخاب‌شده معتبر نیست.',
        ]);

        $status = $data['status'] === 'done' ? 'completed' : $data['status'];
        $status = $status === 'pending' ? 'waiting' : $status;
        $project->update(['status' => $status]);

        $project->load(['projectManager:id,name,job_title,avatar', 'members:id,name,job_title,avatar'])
            ->loadCount([
                'tasks',
                'tasks as done_tasks_count' => fn ($taskQuery) => $taskQuery->where('status', 'done'),
                'tasks as overdue_tasks_count' => fn ($taskQuery) => $taskQuery
                    ->whereDate('due_date', '<', now()->toDateString())
                    ->whereNotIn('status', ['done', 'canceled', 'cancelled']),
            ]);

        return response()->json([
            'success' => true,
            'data' => $this->projectCard($project),
            'message' => 'وضعیت پروژه تغییر کرد.',
        ]);
    }

    public function notifications(Request $request): JsonResponse
    {
        $query = $request->user()->notifications()
            ->whereNull('dismissed_at')
            ->where(function ($innerQuery) {
                $innerQuery->whereNull('remind_at')->orWhere('remind_at', '<=', now());
            });
        $filter = $request->input('filter', 'all');

        match ($filter) {
            'unread' => $query->where(function ($innerQuery) {
                $innerQuery->whereNull('read_at')->orWhere('is_read', false);
            }),
            'tasks' => $query->whereIn('type', ['task_assigned', 'task_new', 'task_created', 'task_status_changed', 'task_overdue']),
            'comments' => $query->whereIn('type', ['comment_created', 'comment_new']),
            'mentions' => $query->where('type', 'mention'),
            'deadlines' => $query->whereIn('type', ['deadline_soon', 'task_overdue']),
            'system' => $query->where('type', 'system'),
            default => null,
        };

        $notifications = $query
            ->latest()
            ->paginate(min((int) $request->input('per_page', 20), 50));

        return response()->json([
            'success' => true,
            'data' => collect($notifications->items())->map(fn (Notification $notification) => $this->notificationPayload($notification))->values(),
            'meta' => [
                'current_page' => $notifications->currentPage(),
                'last_page' => $notifications->lastPage(),
                'per_page' => $notifications->perPage(),
                'total' => $notifications->total(),
                'unread_count' => $this->unreadNotificationsCount($request),
            ],
            'message' => 'اعلان‌های موبایل',
        ]);
    }

    public function notificationRead(Request $request, Notification $notification): JsonResponse
    {
        abort_unless((int) $notification->user_id === (int) $request->user()->id, 403, 'شما به این اعلان دسترسی ندارید.');

        $notification->update([
            'read_at' => now(),
            'is_read' => true,
        ]);

        return response()->json([
            'success' => true,
            'data' => $this->notificationPayload($notification->fresh()),
            'meta' => ['unread_count' => $this->unreadNotificationsCount($request)],
            'message' => 'اعلان خوانده شد.',
        ]);
    }

    public function notificationUnread(Request $request, Notification $notification): JsonResponse
    {
        abort_unless((int) $notification->user_id === (int) $request->user()->id, 403, 'شما به این اعلان دسترسی ندارید.');

        $notification->update([
            'read_at' => null,
            'is_read' => false,
        ]);

        return response()->json([
            'success' => true,
            'data' => $this->notificationPayload($notification->fresh()),
            'meta' => ['unread_count' => $this->unreadNotificationsCount($request)],
            'message' => 'اعلان به حالت خوانده‌نشده برگشت.',
        ]);
    }

    public function notificationRemind(Request $request, Notification $notification): JsonResponse
    {
        abort_unless((int) $notification->user_id === (int) $request->user()->id, 403, 'شما به این اعلان دسترسی ندارید.');

        $notification->update([
            'remind_at' => now()->addMinutes(30),
            'dismissed_at' => null,
            'read_at' => null,
            'is_read' => false,
        ]);

        return response()->json([
            'success' => true,
            'data' => $this->notificationPayload($notification->fresh()),
            'meta' => ['unread_count' => $this->unreadNotificationsCount($request)],
            'message' => '۳۰ دقیقه دیگر یادآوری می‌شود.',
        ]);
    }

    public function notificationDismiss(Request $request, Notification $notification): JsonResponse
    {
        abort_unless((int) $notification->user_id === (int) $request->user()->id, 403, 'شما به این اعلان دسترسی ندارید.');

        $notification->update([
            'dismissed_at' => now(),
        ]);

        return response()->json([
            'success' => true,
            'meta' => ['unread_count' => $this->unreadNotificationsCount($request)],
            'message' => 'اعلان از لیست خارج شد.',
        ]);
    }

    public function notificationsReadAll(Request $request): JsonResponse
    {
        $request->user()->notifications()
            ->where(function ($query) {
                $query->whereNull('read_at')->orWhere('is_read', false);
            })
            ->update([
                'read_at' => now(),
                'is_read' => true,
            ]);

        return response()->json([
            'success' => true,
            'meta' => ['unread_count' => 0],
            'message' => 'همه اعلان‌ها خوانده شدند.',
        ]);
    }

    public function tasks(Request $request): JsonResponse
    {
        $user = $request->user()->loadMissing(['roles.permissions']);
        $query = $this->visibleTasksQuery($user)
            ->with(['project:id,title,status', 'assignee:id,name,job_title'])
            ->withCount(['comments', 'files']);

        $filter = $request->input('filter', 'all');
        $today = now()->toDateString();

        match ($filter) {
            'today' => $query->whereDate('due_date', $today),
            'overdue' => $query->whereDate('due_date', '<', $today)->whereNotIn('status', ['done', 'canceled', 'cancelled']),
            'active' => $query->whereIn('status', ['waiting', 'todo', 'in_progress', 'review']),
            'done' => $query->where('status', 'done'),
            'urgent' => $query->where('priority', 'urgent'),
            default => null,
        };

        if ($request->filled('search')) {
            $search = trim($request->input('search'));
            $query->where(function ($innerQuery) use ($search) {
                $innerQuery->where('title', 'like', "%{$search}%")
                    ->orWhereHas('project', fn ($projectQuery) => $projectQuery->where('title', 'like', "%{$search}%"));
            });
        }

        if ($request->filled('project_id')) {
            $query->where('project_id', $request->input('project_id'));
        }

        $tasks = $query
            ->orderByRaw("case priority when 'urgent' then 0 when 'high' then 1 when 'medium' then 2 else 3 end")
            ->orderByRaw('case when due_date is null then 1 else 0 end')
            ->orderBy('due_date')
            ->latest()
            ->paginate(min((int) $request->input('per_page', 20), 50));

        return response()->json([
            'success' => true,
            'data' => collect($tasks->items())->map(fn (Task $task) => $this->taskCard($task))->values(),
            'meta' => [
                'current_page' => $tasks->currentPage(),
                'last_page' => $tasks->lastPage(),
                'per_page' => $tasks->perPage(),
                'total' => $tasks->total(),
            ],
            'message' => 'تسک‌های موبایل',
        ]);
    }

    public function taskDetail(Request $request, Task $task): JsonResponse
    {
        $this->abortUnlessTaskVisible($request, $task);
        $task->load([
            'project:id,title,status',
            'assignee:id,name,job_title',
            'reporter:id,name,job_title',
            'comments.user:id,name,job_title',
            'files.user:id,name,job_title',
        ])->loadCount(['comments', 'files']);

        return response()->json([
            'success' => true,
            'data' => $this->taskDetailPayload($task),
            'message' => 'جزئیات تسک',
        ]);
    }

    public function updateTaskStatus(Request $request, Task $task): JsonResponse
    {
        $this->abortUnlessTaskVisible($request, $task);

        $data = $request->validate([
            'status' => ['required', Rule::in(['waiting', 'todo', 'in_progress', 'done'])],
        ], [
            'status.required' => 'انتخاب وضعیت الزامی است.',
            'status.in' => 'وضعیت انتخاب‌شده معتبر نیست.',
        ]);

        $task->update(['status' => $data['status']]);
        $this->projectProgressService->calculateProgress($task->project_id);
        $task->load(['project:id,title,status', 'assignee:id,name,job_title'])->loadCount(['comments', 'files']);

        return response()->json([
            'success' => true,
            'data' => $this->taskCard($task->fresh(['project', 'assignee'])->loadCount(['comments', 'files'])),
            'message' => 'وضعیت تسک تغییر کرد.',
        ]);
    }

    public function addTaskComment(Request $request, Task $task): JsonResponse
    {
        $this->abortUnlessTaskVisible($request, $task);

        $data = $request->validate([
            'body' => 'required|string|max:3000',
        ], [
            'body.required' => 'متن کامنت الزامی است.',
            'body.max' => 'متن کامنت بیش از حد طولانی است.',
        ]);

        $comment = Comment::create([
            'body' => $data['body'],
            'user_id' => $request->user()->id,
            'commentable_id' => $task->id,
            'commentable_type' => Task::class,
        ])->load('user');

        return response()->json([
            'success' => true,
            'data' => new CommentResource($comment),
            'message' => 'کامنت ثبت شد.',
        ], 201);
    }

    public function addTaskAttachment(Request $request, Task $task): JsonResponse
    {
        $this->abortUnlessTaskVisible($request, $task);

        $request->validate([
            'file' => 'required|file|max:10240|mimes:pdf,doc,docx,xls,xlsx,ppt,pptx,txt,csv,jpg,jpeg,png,webp,zip',
        ], [
            'file.required' => 'انتخاب فایل الزامی است.',
            'file.max' => 'حجم فایل نباید بیشتر از ۱۰ مگابایت باشد.',
            'file.mimes' => 'نوع فایل انتخاب‌شده مجاز نیست.',
        ]);

        $uploadedFile = $request->file('file');
        $extension = strtolower($uploadedFile->getClientOriginalExtension());
        $name = Str::uuid()->toString().($extension ? ".{$extension}" : '');
        $path = $uploadedFile->storeAs('files', $name, 'local');

        $file = File::create([
            'name' => $name,
            'original_name' => $uploadedFile->getClientOriginalName(),
            'path' => $path,
            'mime_type' => $uploadedFile->getMimeType(),
            'size' => $uploadedFile->getSize(),
            'fileable_id' => $task->id,
            'fileable_type' => Task::class,
            'user_id' => $request->user()->id,
        ])->load('user');

        return response()->json([
            'success' => true,
            'data' => new FileResource($file),
            'message' => 'فایل با موفقیت آپلود شد.',
        ], 201);
    }

    public function downloadTaskAttachment(Request $request, Task $task, File $file)
    {
        $this->abortUnlessTaskVisible($request, $task);

        if ($file->fileable_type !== Task::class || (int) $file->fileable_id !== (int) $task->id) {
            abort(404);
        }

        $disk = Storage::disk('local')->exists($file->path) ? 'local' : 'public';
        abort_unless(Storage::disk($disk)->exists($file->path), 404);

        return response()->download(Storage::disk($disk)->path($file->path), $file->original_name);
    }

    public function taskOptions(Request $request): JsonResponse
    {
        $user = $request->user()->loadMissing(['roles.permissions']);

        if (! $user->hasPermission('tasks.create')) {
            return response()->json([
                'success' => false,
                'message' => 'شما مجوز ایجاد تسک را ندارید.',
            ], 403);
        }

        $projectQuery = Project::query()
            ->with(['members:id,name,job_title,avatar', 'projectManager:id,name,job_title,avatar'])
            ->when(! $user->hasPermission('reports.view'), function ($query) use ($user) {
                $query->where(function ($scopeQuery) use ($user) {
                    $scopeQuery->where('project_manager_id', $user->id)
                        ->orWhere('created_by', $user->id)
                        ->orWhereHas('members', fn ($memberQuery) => $memberQuery->where('users.id', $user->id));
                });
            })
            ->where(function ($query) {
                $query->where('is_archived', false)->orWhereNull('is_archived');
            })
            ->orderBy('title');

        $projects = $projectQuery->limit(100)->get();
        $projectUserIds = $projects
            ->flatMap(fn (Project $project) => $project->members->pluck('id')->push($project->project_manager_id))
            ->filter()
            ->unique()
            ->values();

        $users = User::query()
            ->when(! $user->hasPermission('reports.view'), function ($query) use ($user, $projectUserIds) {
                $query->where('id', $user->id)
                    ->when($projectUserIds->isNotEmpty(), fn ($innerQuery) => $innerQuery->orWhereIn('id', $projectUserIds));
            })
            ->where(function ($query) {
                $query->where('status', 'active')->orWhereNull('status');
            })
            ->orderBy('name')
            ->limit(200)
            ->get(['id', 'name', 'job_title', 'avatar']);

        return response()->json([
            'success' => true,
            'data' => [
                'projects' => $projects->map(fn (Project $project) => [
                    'id' => $project->id,
                    'title' => $project->title,
                    'members' => $project->members
                        ->push($project->projectManager)
                        ->filter()
                        ->unique('id')
                        ->values()
                        ->map(fn (User $member) => [
                            'id' => $member->id,
                            'name' => $member->name,
                            'job_title' => $member->job_title,
                        ]),
                ])->values(),
                'users' => $users->map(fn (User $optionUser) => [
                    'id' => $optionUser->id,
                    'name' => $optionUser->name,
                    'job_title' => $optionUser->job_title,
                ])->values(),
                'priorities' => [
                    ['value' => 'low', 'label' => 'کم'],
                    ['value' => 'medium', 'label' => 'متوسط'],
                    ['value' => 'high', 'label' => 'زیاد'],
                    ['value' => 'urgent', 'label' => 'فوری'],
                ],
            ],
            'message' => 'گزینه‌های ایجاد تسک',
        ]);
    }

    public function sprints(Request $request): JsonResponse
    {
        $user = $request->user()->loadMissing(['roles.permissions']);

        $query = Sprint::query()->with('project:id,title,status');

        if (! $user->hasPermission('reports.view')) {
            $visibleProjectIds = $this->visibleProjectsQuery($user)->pluck('id');

            $query->where(function ($scopeQuery) use ($user, $visibleProjectIds) {
                $scopeQuery
                    ->when($visibleProjectIds->isNotEmpty(), fn ($innerQuery) => $innerQuery->whereIn('project_id', $visibleProjectIds))
                    ->orWhereHas('members', fn ($memberQuery) => $memberQuery->where('users.id', $user->id))
                    ->orWhereHas('tasks', function ($taskQuery) use ($user) {
                        $taskQuery
                            ->where('assignee_id', $user->id)
                            ->orWhere('reporter_id', $user->id)
                            ->orWhere('created_by', $user->id);
                    });
            });
        }

        $sprints = $query
            ->orderByRaw("case when status = 'active' then 0 when status in ('planning','planned') then 1 else 2 end")
            ->orderByRaw('case when end_date is null then 1 else 0 end')
            ->orderByDesc('end_date')
            ->orderByDesc('start_date')
            ->limit(8)
            ->get();

        return response()->json([
            'success' => true,
            'data' => $sprints->map(fn (Sprint $sprint) => $this->pwaSprintPayload($sprint, $user))->values(),
            'message' => 'اسپرینت‌های موبایل',
        ]);
    }

    public function home(Request $request): JsonResponse
    {
        $user = $request->user()->loadMissing(['roles.permissions']);
        $today = now()->toDateString();
        $openStatuses = ['waiting', 'todo', 'in_progress', 'review'];

        $myTasks = Task::query()
            ->with(['project:id,title,status'])
            ->where('assignee_id', $user->id);

        $todayTasks = (clone $myTasks)
            ->whereDate('due_date', $today)
            ->whereIn('status', $openStatuses);

        $overdueTasks = (clone $myTasks)
            ->whereDate('due_date', '<', $today)
            ->whereNotIn('status', ['done', 'canceled', 'cancelled']);

        $activeTasks = (clone $myTasks)
            ->whereIn('status', ['todo', 'in_progress', 'review', 'waiting']);

        $importantTasks = (clone $myTasks)
            ->whereIn('status', $openStatuses)
            ->orderByRaw("case priority when 'urgent' then 0 when 'high' then 1 when 'medium' then 2 else 3 end")
            ->orderByRaw('case when due_date is null then 1 else 0 end')
            ->orderBy('due_date')
            ->limit(5)
            ->get()
            ->map(fn (Task $task) => $this->taskPreview($task))
            ->values();

        $notifications = Notification::query()
            ->where('user_id', $user->id)
            ->latest()
            ->limit(5)
            ->get()
            ->map(fn (Notification $notification) => [
                'id' => $notification->id,
                'type' => $notification->type,
                'title' => $notification->title,
                'body' => $notification->body,
                'data' => $notification->data,
                'notifiable_type' => $notification->notifiable_type,
                'notifiable_id' => $notification->notifiable_id,
                'is_read' => (bool) $notification->is_read,
                'created_at' => $notification->created_at,
            ])
            ->values();

        $permissions = $user->roles
            ->flatMap(fn ($role) => $role->permissions->pluck('name'))
            ->unique()
            ->values();

        $canViewTeamScope = $user->hasAnyPermission(['reports.view', 'team.view', 'tasks.edit']);
        $managerSummary = null;

        if ($canViewTeamScope) {
            $manageableProjectIds = $this->manageableProjectIds($user);

            $teamTaskQuery = Task::query()
                ->when($manageableProjectIds->isNotEmpty(), fn ($query) => $query->whereIn('project_id', $manageableProjectIds))
                ->when($manageableProjectIds->isEmpty() && ! $user->hasPermission('reports.view'), fn ($query) => $query->whereRaw('1 = 0'));

            $managerSummary = [
                'overdue_team_tasks' => (clone $teamTaskQuery)
                    ->whereDate('due_date', '<', $today)
                    ->whereNotIn('status', ['done', 'canceled', 'cancelled'])
                    ->count(),
                'review_tasks' => (clone $teamTaskQuery)->where('status', 'review')->count(),
                'active_sprint' => Sprint::query()
                    ->with('project:id,title')
                    ->where('status', 'active')
                    ->when($manageableProjectIds->isNotEmpty(), fn ($query) => $query->whereIn('project_id', $manageableProjectIds))
                    ->latest()
                    ->first()?->only(['id', 'title', 'project_id', 'start_date', 'end_date']),
                'delayed_members' => (clone $teamTaskQuery)
                    ->whereDate('due_date', '<', $today)
                    ->whereNotIn('status', ['done', 'canceled', 'cancelled'])
                    ->whereNotNull('assignee_id')
                    ->distinct('assignee_id')
                    ->count('assignee_id'),
            ];
        }

        return response()->json([
            'success' => true,
            'data' => [
                'user' => [
                    'id' => $user->id,
                    'name' => $user->name,
                    'job_title' => $user->job_title,
                    'role_label' => $user->roles->first()?->display_name,
                ],
                'permissions' => $permissions,
                'stats' => [
                    'today_tasks' => $todayTasks->count(),
                    'overdue_tasks' => $overdueTasks->count(),
                    'active_tasks' => $activeTasks->count(),
                    'unread_notifications' => Notification::where('user_id', $user->id)->where('is_read', false)->count(),
                ],
                'tasks' => $importantTasks,
                'notifications' => $notifications,
                'manager_summary' => $managerSummary,
            ],
            'message' => 'خانه موبایل',
        ]);
    }

    private function taskPreview(Task $task): array
    {
        return [
            'id' => $task->id,
            'title' => $task->title,
            'status' => $task->status,
            'priority' => $task->priority,
            'due_date' => $task->due_date?->format('Y-m-d'),
            'project' => $task->project ? [
                'id' => $task->project->id,
                'title' => $task->project->title,
            ] : null,
        ];
    }

    private function profileAccessSummary($permissions, User $user): array
    {
        $items = [
            ['permissions' => ['projects.view'], 'label' => 'مشاهده پروژه‌ها'],
            ['permissions' => ['projects.edit', 'projects.create'], 'label' => 'مدیریت پروژه‌ها'],
            ['permissions' => ['tasks.view'], 'label' => 'مشاهده تسک‌ها'],
            ['permissions' => ['tasks.create'], 'label' => 'ایجاد تسک'],
            ['permissions' => ['tasks.edit'], 'label' => 'تغییر وضعیت تسک'],
            ['permissions' => ['comments.create'], 'label' => 'ثبت کامنت'],
            ['permissions' => ['files.upload'], 'label' => 'آپلود فایل'],
            ['permissions' => ['notifications.view'], 'label' => 'مشاهده اعلان‌ها'],
            ['permissions' => ['reports.view'], 'label' => 'مشاهده گزارش‌ها'],
        ];

        $permissionSet = $permissions->flip();
        $summary = collect($items)
            ->filter(fn ($item) => collect($item['permissions'])->contains(fn ($permission) => $permissionSet->has($permission)))
            ->map(fn ($item) => ['label' => $item['label']])
            ->values();

        $isAdmin = $user->roles->contains(fn ($role) => in_array($role->name, ['admin', 'super_admin', 'system_admin'], true))
            || $permissionSet->has('roles.edit')
            || $permissionSet->has('settings.edit');

        return [
            'is_admin' => $isAdmin,
            'items' => $summary,
        ];
    }

    private function manageableProjectIds($user)
    {
        if ($user->hasPermission('reports.view')) {
            return collect();
        }

        return $user->managedProjects()->pluck('id')
            ->merge($user->projects()->pluck('projects.id'))
            ->unique()
            ->values();
    }

    private function visibleTasksQuery(User $user)
    {
        return $this->resourceAccess->tasks($user);
    }

    private function abortUnlessTaskVisible(Request $request, Task $task): void
    {
        $user = $request->user()->loadMissing(['roles.permissions']);
        $allowed = $this->visibleTasksQuery($user)->where('id', $task->id)->exists();
        abort_unless($allowed, 403, 'شما به این تسک دسترسی ندارید.');
    }

    private function visibleProjectsQuery(User $user)
    {
        return $this->resourceAccess->projects($user);
    }

    private function abortUnlessProjectVisible(Request $request, Project $project): void
    {
        $user = $request->user()->loadMissing(['roles.permissions']);
        $allowed = $this->visibleProjectsQuery($user)->where('id', $project->id)->exists();
        abort_unless($allowed, 403, 'شما به این پروژه دسترسی ندارید.');
    }

    private function projectCard(Project $project): array
    {
        return [
            'id' => $project->id,
            'title' => $project->title,
            'description' => $project->description,
            'status' => $project->status,
            'progress' => (int) ($project->progress ?? 0),
            'due_date' => $project->end_date?->format('Y-m-d'),
            'manager' => $project->projectManager ? [
                'id' => $project->projectManager->id,
                'name' => $project->projectManager->name,
            ] : null,
            'task_counts' => [
                'total' => $project->tasks_count ?? 0,
                'done' => $project->done_tasks_count ?? 0,
                'overdue' => $project->overdue_tasks_count ?? 0,
            ],
            'members_preview' => $project->relationLoaded('members')
                ? $project->members->take(4)->map(fn (User $member) => [
                    'id' => $member->id,
                    'name' => $member->name,
                    'avatar_url' => $member->avatar ? asset('storage/'.$member->avatar) : null,
                ])->values()
                : [],
        ];
    }

    private function notificationPayload(Notification $notification): array
    {
        $data = $notification->data ?? [];

        return [
            'id' => $notification->id,
            'type' => $notification->type,
            'title' => $notification->title,
            'body' => $notification->body,
            'message' => $notification->body,
            'data' => [
                'task_id' => $data['task_id'] ?? null,
                'project_id' => $data['project_id'] ?? null,
                'comment_id' => $data['comment_id'] ?? null,
                'target_type' => $data['target_type'] ?? $data['targetType'] ?? null,
                'target_id' => $data['target_id'] ?? $data['targetId'] ?? null,
            ],
            'notifiable_type' => $notification->notifiable_type,
            'notifiable_id' => $notification->notifiable_id,
            'is_read' => (bool) $notification->is_read || $notification->read_at !== null,
            'read_at' => $notification->read_at,
            'remind_at' => $notification->remind_at,
            'dismissed_at' => $notification->dismissed_at,
            'created_at' => $notification->created_at,
        ];
    }

    private function unreadNotificationsCount(Request $request): int
    {
        return $request->user()->notifications()
            ->whereNull('dismissed_at')
            ->where(function ($outerQuery) {
                $outerQuery->whereNull('remind_at')->orWhere('remind_at', '<=', now());
            })
            ->where(function ($query) {
                $query->whereNull('read_at')->orWhere('is_read', false);
            })
            ->count();
    }

    private function taskCard(Task $task): array
    {
        $latestComment = $task->relationLoaded('comments')
            ? $task->comments->sortByDesc('created_at')->first()
            : $task->comments()->latest()->first();

        return [
            'id' => $task->id,
            'title' => $task->title,
            'status' => $task->status,
            'priority' => $task->priority,
            'due_date' => $task->due_date?->format('Y-m-d'),
            'created_at' => $task->created_at,
            'project' => $task->project ? [
                'id' => $task->project->id,
                'title' => $task->project->title,
            ] : null,
            'assignee' => $task->assignee ? [
                'id' => $task->assignee->id,
                'name' => $task->assignee->name,
            ] : null,
            'comments_count' => $task->comments_count,
            'files_count' => $task->files_count,
            'latest_comment' => $latestComment ? [
                'id' => $latestComment->id,
                'body' => Str::limit($latestComment->body, 90),
                'created_at' => $latestComment->created_at,
            ] : null,
        ];
    }

    private function pwaSprintPayload(Sprint $sprint, User $user): array
    {
        $today = now()->toDateString();
        $tasks = $this->visibleTasksQuery($user)
            ->whereHas('sprints', fn ($sprintQuery) => $sprintQuery->where('sprints.id', $sprint->id))
            ->with(['project:id,title,status', 'assignee:id,name,job_title'])
            ->withCount(['comments', 'files'])
            ->orderByRaw("case priority when 'urgent' then 0 when 'high' then 1 when 'medium' then 2 else 3 end")
            ->orderByRaw('case when due_date is null then 1 else 0 end')
            ->orderBy('due_date')
            ->get();

        $total = $tasks->count();
        $done = $tasks->where('status', 'done')->count();
        $inProgress = $tasks->whereIn('status', ['in_progress', 'review'])->count();
        $overdue = $tasks
            ->filter(fn (Task $task) => $task->due_date && $task->due_date->format('Y-m-d') < $today && ! in_array($task->status, ['done', 'canceled', 'cancelled'], true))
            ->count();
        $progress = $total > 0 ? (int) round(($done / $total) * 100) : 0;
        $remainingDays = $sprint->end_date ? now()->startOfDay()->diffInDays($sprint->end_date->copy()->startOfDay(), false) : null;

        return [
            'id' => $sprint->id,
            'title' => $sprint->title,
            'status' => $sprint->status,
            'goal' => $sprint->goal,
            'start_date' => $sprint->start_date?->format('Y-m-d'),
            'end_date' => $sprint->end_date?->format('Y-m-d'),
            'remaining_days' => $remainingDays,
            'progress' => $progress,
            'project' => $sprint->project ? [
                'id' => $sprint->project->id,
                'title' => $sprint->project->title,
            ] : null,
            'task_counts' => [
                'total' => $total,
                'done' => $done,
                'in_progress' => $inProgress,
                'overdue' => $overdue,
            ],
            'tasks' => $tasks->map(fn (Task $task) => $this->taskCard($task))->values(),
            'capabilities' => [
                'can_create_task' => $user->hasPermission('tasks.create'),
                'can_update_task_status' => $user->hasPermission('tasks.edit'),
                'can_comment' => $user->hasPermission('comments.create'),
            ],
        ];
    }

    private function taskDetailPayload(Task $task): array
    {
        return array_merge($this->taskCard($task), [
            'description' => $task->description,
            'reporter' => $task->reporter ? [
                'id' => $task->reporter->id,
                'name' => $task->reporter->name,
            ] : null,
            'comments' => CommentResource::collection($task->comments->sortByDesc('created_at')->values()),
            'files' => FileResource::collection($task->files->sortByDesc('created_at')->values()),
        ]);
    }
}
