<?php

namespace App\Http\Middleware;

use App\Models\BacklogItem;
use App\Models\Checklist;
use App\Models\Comment;
use App\Models\File;
use App\Models\Meeting;
use App\Models\MeetingActionItem;
use App\Models\Notification;
use App\Models\Project;
use App\Models\Sprint;
use App\Models\Subtask;
use App\Models\Task;
use App\Services\ResourceAccessService;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;

class EnsureResourceAccess
{
    public function __construct(private readonly ResourceAccessService $access) {}

    public function handle(Request $request, Closure $next): Response
    {
        $user = $request->user();
        if (! $user) {
            return response()->json(['success' => false, 'message' => 'Unauthenticated.'], 401);
        }

        $route = $request->route();
        $checks = [
            'project' => fn ($model) => $model instanceof Project && $this->access->canAccessProject($user, $model),
            'task' => fn ($model) => $model instanceof Task && $this->access->canAccessTask($user, $model),
            'sprint' => fn ($model) => $model instanceof Sprint && $this->access->canAccessSprint($user, $model),
            'meeting' => fn ($model) => $model instanceof Meeting && $this->access->canAccessMeeting($user, $model),
            'comment' => fn ($model) => $model instanceof Comment && $this->access->canAccessComment($user, $model),
            'file' => fn ($model) => $model instanceof File && $this->access->canAccessFile($user, $model),
            'backlogItem' => fn ($model) => $model instanceof BacklogItem
                && ($this->access->canSeeAll($user)
                    || $model->created_by === $user->id
                    || ($model->project_id !== null
                        && $this->access->projects($user)->whereKey($model->project_id)->exists())),
            'checklist' => fn ($model) => $model instanceof Checklist && $this->access->tasks($user)->whereKey($model->task_id)->exists(),
            'subtask' => fn ($model) => $model instanceof Subtask && $this->access->tasks($user)->whereKey($model->task_id)->exists(),
            'notification' => fn ($model) => $model instanceof Notification && $model->user_id === $user->id,
        ];

        foreach ($checks as $parameter => $allowed) {
            $model = $route?->parameter($parameter);
            if ($model !== null && ! $allowed($model)) {
                abort(403, 'شما به این منبع دسترسی ندارید.');
            }
        }

        $actionItem = $route?->parameter('actionItem');
        $meeting = $route?->parameter('meeting');
        if ($actionItem instanceof MeetingActionItem) {
            abort_unless(
                $meeting instanceof Meeting
                && $actionItem->meeting_id === $meeting->id
                && $this->access->canAccessMeeting($user, $meeting),
                403,
                'این اقدام متعلق به جلسه انتخاب‌شده نیست.'
            );
        }

        return $next($request);
    }
}
