<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\DB;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

class RoleController extends Controller
{
    /** helper: get guards list */
    private function guards()
    {
        $guards = Role::select('guard_name')->distinct()->pluck('guard_name')->filter()->values();

        if ($guards->isEmpty()) {
            $guards = collect(['web']);
        }

        // also include permissions guards (if roles table empty)
        $pGuards = Permission::select('guard_name')->distinct()->pluck('guard_name')->filter()->values();
        $guards = $guards->merge($pGuards)->unique()->values();

        if ($guards->isEmpty()) {
            $guards = collect(['web']);
        }

        return $guards;
    }

    /** List + search + filter + paginate */
    public function index(Request $request)
    {
        $q          = trim($request->get('q', ''));
        $guard_name = $request->get('guard_name');

        $query = Role::query();

        if ($q !== '') {
            $query->where('name', 'like', "%{$q}%");
        }
        if (!empty($guard_name)) {
            $query->where('guard_name', $guard_name);
        }

        $roles  = $query->orderBy('id', 'desc')->paginate(20)->withQueryString();
        $guards = $this->guards();

        return view('roles.index', compact('roles', 'q', 'guard_name', 'guards'));
    }

    /** Create form */
    public function create(Request $request)
    {
        $guards = $this->guards();
        $guard  = $request->get('guard_name', 'web');

        // ✅ permissions only for selected guard
        $permissions = Permission::where('guard_name', $guard)->orderBy('name')->get();

        return view('roles.create', [
            'guards' => $guards,
            'permissions' => $permissions,
            'guard_name' => $guard,
        ]);
    }

    /** Store */
    public function store(Request $request)
    {
        $data = $request->validate([
            'name'          => ['required', 'string', 'max:191', 'unique:roles,name'],
            'guard_name'    => ['nullable', 'string', 'max:191'],
            'permissions'   => ['nullable', 'array'],
            'permissions.*' => ['integer'], // ✅ we will validate with guard below
        ]);

        $guard = $data['guard_name'] ?: 'web';

        DB::transaction(function () use ($data, $guard) {

            /** @var Role $role */
            $role = Role::create([
                'name'       => $data['name'],
                'guard_name' => $guard,
            ]);

            $permIds = $data['permissions'] ?? [];

            if (!empty($permIds)) {
                // ✅ Only permissions that belong to same guard
                $perms = Permission::whereIn('id', $permIds)
                    ->where('guard_name', $guard)
                    ->get();

                // ✅ sync with Permission models (NOT ids)
                $role->syncPermissions($perms);
            }
        });

        return redirect()->route('roles.index')->with('msg', 'Role created successfully.');
    }

    /** Show */
    public function show($id)
    {
        $role = Role::findOrFail($id);

        $rolePermissions = $role->permissions()
            ->orderBy('name')
            ->paginate(20)
            ->withQueryString();

        return view('roles.show', compact('role', 'rolePermissions'));
    }

    /** Edit form */
    public function edit($id)
    {
        $role   = Role::findOrFail($id);
        $guards = $this->guards();

        // ✅ permissions only for role guard
        $permissions = Permission::where('guard_name', $role->guard_name)->orderBy('name')->get();

        $rolePermissionIds = $role->permissions->pluck('id')->toArray();

        return view('roles.edit', compact('role', 'guards', 'permissions', 'rolePermissionIds'));
    }

    /** Update */
    public function update(Request $request, $id)
    {
        $role = Role::findOrFail($id);

        $data = $request->validate([
            'name'          => ['required', 'string', 'max:191', Rule::unique('roles', 'name')->ignore($role->id)],
            'guard_name'    => ['nullable', 'string', 'max:191'],
            'permissions'   => ['nullable', 'array'],
            'permissions.*' => ['integer'],
        ]);

        // ⚠️ best practice: do NOT allow changing guard_name after creation
        // because spatie relations depend on guard. We'll keep current guard.
        $guard = $role->guard_name ?: 'web';

        DB::transaction(function () use ($role, $data, $guard) {

            $role->update([
                'name' => $data['name'],
                // 'guard_name' => $guard, // keep unchanged
            ]);

            $permIds = $data['permissions'] ?? [];

            // ✅ same guard only
            $perms = Permission::whereIn('id', $permIds)
                ->where('guard_name', $guard)
                ->get();

            $role->syncPermissions($perms);
        });

        return redirect()->route('roles.index')->with('msg', 'Role updated successfully.');
    }

    /** Destroy */
    public function destroy($id)
    {
        $role = Role::findOrFail($id);

        if (strtolower($role->name) === 'super admin') {
            return redirect()->back()->with('msg', 'Super Admin role cannot be deleted.');
        }

        DB::transaction(function () use ($role) {
            $role->syncPermissions([]);
            $role->delete();
        });

        return redirect()->route('roles.index')->with('msg', 'Role deleted.');
    }
}
