<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class RoleMiddleware
{
    public function handle(Request $request, Closure $next, string ...$roles): mixed
    {
        $user = $request->user();

        if (! $user) {
            return redirect()->route('login');
        }

        if (! $user->is_active) {
            auth()->logout();
            return redirect()->route('login')->with('error', 'Your account has been deactivated.');
        }

        $userRole = $user->role?->name ?? 'staff';

        // office_admin can access everything
        if ($userRole === 'office_admin') {
            return $next($request);
        }

        // Map route names to DB permission keys
        $routeName = $request->route()?->getName();
        $routePermissionMap = [
            'leads.index'        => 'leads.view',
            'leads.show'         => 'leads.view',
            'leads.create'       => 'leads.create',
            'leads.store'        => 'leads.create',
            'leads.edit'         => 'leads.edit',
            'leads.update'       => 'leads.edit',
            'leads.destroy'      => 'leads.delete',
            'leads.convert'      => 'leads.convert',
            'jobs.index'         => 'jobs.view',
            'jobs.show'          => 'jobs.view',
            'jobs.create'        => 'jobs.create',
            'jobs.store'         => 'jobs.create',
            'jobs.edit'          => 'jobs.edit',
            'jobs.update'        => 'jobs.edit',
            'jobs.destroy'       => 'jobs.delete',
            'jobs.advance_stage' => 'jobs.advance_stage',
            'contacts.index'     => 'contacts.view',
            'contacts.show'      => 'contacts.view',
            'contacts.create'    => 'contacts.create',
            'contacts.store'     => 'contacts.create',
            'contacts.edit'      => 'contacts.edit',
            'contacts.update'    => 'contacts.edit',
            'contacts.destroy'   => 'contacts.delete',
            'quotes.index'       => 'quotes.view',
            'quotes.show'        => 'quotes.view',
            'quotes.create'      => 'quotes.create',
            'quotes.store'       => 'quotes.create',
            'quotes.edit'        => 'quotes.edit',
            'quotes.update'      => 'quotes.edit',
            'quotes.destroy'     => 'quotes.delete',
            'quotes.convert'     => 'quotes.convert',
            'contracts.index'    => 'contracts.view',
            'contracts.show'     => 'contracts.view',
            'contracts.create'   => 'contracts.create',
            'contracts.store'    => 'contracts.create',
            'contracts.edit'     => 'contracts.edit',
            'contracts.update'   => 'contracts.edit',
            'contracts.destroy'  => 'contracts.delete',
            'check_measure.index'  => 'check_measure.view',
            'check_measure.show'   => 'check_measure.view',
            'check_measure.create' => 'check_measure.create',
            'check_measure.store'  => 'check_measure.create',
            'check_measure.edit'   => 'check_measure.edit',
            'check_measure.update' => 'check_measure.edit',
            'processing.index'  => 'processing.view',
            'processing.show'   => 'processing.view',
            'processing.store_order'   => 'processing.manage',
            'processing.update_order'  => 'processing.manage',
            'processing.update_progress' => 'processing.manage',
            'delivery.index'    => 'delivery.view',
            'delivery.show'     => 'delivery.view',
            'delivery.create'   => 'delivery.manage',
            'delivery.store'    => 'delivery.manage',
            'delivery.edit'     => 'delivery.manage',
            'delivery.update'   => 'delivery.manage',
            'delivery.deliver'  => 'delivery.manage',
            'delivery.destroy'  => 'delivery.manage',
            'installation.index'  => 'installation.view',
            'installation.show'   => 'installation.view',
            'installation.create' => 'installation.manage',
            'installation.store'  => 'installation.manage',
            'installation.edit'   => 'installation.manage',
            'installation.update' => 'installation.manage',
            'installation.complete' => 'installation.manage',
            'installation.destroy'  => 'installation.manage',
            'completion.index'  => 'completion.view',
            'completion.show'   => 'completion.view',
            'completion.create' => 'completion.manage',
            'completion.store'  => 'completion.manage',
            'completion.edit'   => 'completion.manage',
            'completion.update' => 'completion.manage',
            'completion.destroy' => 'completion.manage',
            'timesheet.index'   => 'timesheet.view',
            'timesheet.admin'   => 'timesheet.admin',
            'staff-invoices.index' => 'staff_invoices.view',
            'staff-invoices.show'  => 'staff_invoices.view',
            'staff-invoices.approve' => 'staff_invoices.approve',
            'staff-invoices.reject'  => 'staff_invoices.approve',
            'staff-invoices.paid'    => 'staff_invoices.approve',
            'reports.index'     => 'reports.view',
            'reports.timesheet' => 'reports.view',
            'calendar.index'    => 'calendar.view',
            'calendar.store'    => 'calendar.manage',
            'calendar.update'   => 'calendar.manage',
            'calendar.destroy'  => 'calendar.manage',
        ];

        // If we have a DB permission mapping, check it first
        if ($routeName && isset($routePermissionMap[$routeName]) && $user->role_id) {
            $permKey = $routePermissionMap[$routeName];
            $record = \App\Models\RolePermission::where('role_id', $user->role_id)
                ->where('permission', $permKey)
                ->first();

            if ($record !== null) {
                // Explicit DB setting exists — honour it
                if ($record->granted) {
                    return $next($request);
                }
                if ($request->expectsJson()) {
                    return response()->json(['error' => 'Forbidden'], 403);
                }
                abort(403, 'You do not have permission to access this area.');
            }
        }

        if (! empty($roles) && ! in_array($userRole, $roles)) {
            if ($request->expectsJson()) {
                return response()->json(['error' => 'Forbidden'], 403);
            }
            abort(403, 'You do not have permission to access this area.');
        }

        return $next($request);
    }
}
