<?php

namespace App\Http\Middleware;

use App\Http\Controllers\Admin\RoleController;
use App\Models\Admin;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response;

class AdminMiddleware
{
    /**
     * Role hierarchy levels — higher value = more privileged.
     * Used to enforce that admins cannot manage users at or above their own level.
     */
    private const ROLE_HIERARCHY = [
        'super_admin' => 4,
        'admin'       => 3,
        'moderator'   => 2,
        'support'     => 1,
    ];

    /**
     * Determine whether the actor role outranks the target role.
     *
     * Returns true only when the actor is strictly above the target in the
     * hierarchy. Unknown roles are treated as level 0 (unprivileged).
     */
    public static function canManageRole(string $actorRole, string $targetRole): bool
    {
        $actorLevel  = self::ROLE_HIERARCHY[$actorRole]  ?? 0;
        $targetLevel = self::ROLE_HIERARCHY[$targetRole] ?? 0;

        return $actorLevel > $targetLevel;
    }

    /**
     * Get the numeric hierarchy level for a role (0 for unknown roles).
     */
    public static function getRoleLevel(string $role): int
    {
        return self::ROLE_HIERARCHY[$role] ?? 0;
    }

    public function handle(Request $request, Closure $next, ?string $role = null): Response
    {
        $user = auth()->user();

        // Recognise BOTH guards' user shapes. The /admin/* routes use
        // auth:admin, which flips the active guard to 'admin' — so
        // auth()->user() returns an App\Models\Admin instance with $role
        // and no $is_admin. Treat both as valid admins.
        $isAdminUser = $user instanceof Admin
            || Auth::guard('admin')->check()
            || (! empty($user?->is_admin));

        if (!auth()->check() || !$user || !$isAdminUser) {
            Log::warning('AdminMiddleware: REJECT — not authenticated or not an admin', [
                'auth_check' => auth()->check(),
                'has_user'   => (bool) $user,
                'user_class' => $user ? get_class($user) : null,
            ]);
            if ($request->expectsJson()) {
                return response()->json(['message' => 'Unauthorized.'], 403);
            }
            abort(403, 'Unauthorized.');
        }

        // FIX-014: Check if admin account is active (User model only —
        // Admin model has no status column, so admin-guard users are
        // assumed active until explicitly suspended via other means).
        if ($user instanceof Admin) {
            $status = 'active';
        } else {
            $status = $user->status ?? 'active';
        }
        if ($status !== 'active') {
            auth()->logout();
            if ($request->expectsJson()) {
                return response()->json(['message' => 'Account suspended.'], 403);
            }
            abort(403, 'Your admin account has been suspended.');
        }

        // Resolve role from whichever model is active. Admin uses `role`,
        // User uses `admin_role`.
        $effectiveRole = $user instanceof Admin
            ? ($user->role ?? 'support')
            : ($user->admin_role ?? 'support');

        // Optional explicit role check — e.g. middleware('admin:super_admin')
        if ($role && $effectiveRole !== $role) {
            if ($request->expectsJson()) {
                return response()->json(['message' => 'Insufficient admin privileges.'], 403);
            }
            abort(403, 'Insufficient admin privileges.');
        }

        // ── Role-based module access control ──────────────────────────
        // super_admin bypasses all checks
        if ($effectiveRole === 'super_admin') {
            return $next($request);
        }

        $module = RoleController::resolveModule($request->path());

        // Allow the base /admin redirect (no module)
        if ($module === null || $module === '') {
            return $next($request);
        }

        // Check if the user's role has access to this module
        $adminRole = $effectiveRole;

        if (! RoleController::roleHasAccess($adminRole, $module)) {
            if ($request->expectsJson()) {
                return response()->json([
                    'message' => 'You do not have permission to access this section.',
                ], 403);
            }

            return redirect()->route('admin.dashboard')
                ->with('error', 'You do not have permission to access that section.');
        }

        // For support role: block mutating requests on view-only modules
        if ($adminRole === 'support' && in_array($module, RoleController::SUPPORT_VIEW_ONLY, true)) {
            if (! $request->isMethod('GET')) {
                if ($request->expectsJson()) {
                    return response()->json([
                        'message' => 'Your role has read-only access to this section.',
                    ], 403);
                }

                return redirect()->back()
                    ->with('error', 'Your role has read-only access to this section.');
            }
        }

        return $next($request);
    }
}
