<?php

namespace App\Http\Controllers\Company\Admin;

use App\Http\Controllers\Controller;
use App\Models\{AuditLog, Permission, Role};
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;

class RolesController extends Controller
{
    public function index()
    {
        $this->authorize_permission('users', 'view');

        $roles = Role::withCount('users')->orderBy('is_system', 'desc')->orderBy('name')->get();
        return view('admin.roles.index', compact('roles'));
    }

    public function create()
    {
        $this->authorize_permission('users', 'create');

        $permissions = Permission::orderBy('module')->orderBy('action')->get()
            ->groupBy('module');

        return view('admin.roles.create', compact('permissions'));
    }

    public function store(Request $request)
    {
        $this->authorize_permission('users', 'create');

        $companyId = auth()->user()->company_id;

        $validated = $request->validate([
            'name'         => [
                'required','string','max:100',
                Rule::unique('roles')->where(fn($q) => $q->where('company_id', $companyId)),
            ],
            'display_name' => 'nullable|string|max:100',
            'description'  => 'nullable|string|max:500',
            'permissions'  => 'nullable|array',
            'permissions.*'=> 'integer|exists:permissions,id',
        ]);

        $role = Role::create([
            'company_id'   => $companyId,
            'name'         => $validated['name'],
            'display_name' => $validated['display_name'] ?? $validated['name'],
            'description'  => $validated['description'] ?? null,
            'is_system'    => false,
        ]);

        if (!empty($validated['permissions'])) {
            $role->permissions()->sync($validated['permissions']);
        }

        AuditLog::record('create', 'roles', (string) $role->id, null,
            ['name' => $role->name, 'permissions' => count($validated['permissions'] ?? [])],
            "Role created: {$role->name}");

        return redirect()->route('admin.roles.index')
            ->with('success', "Role '{$role->name}' created successfully.");
    }

    public function edit(Role $role)
    {
        $this->authorize_permission('users', 'edit');
        $this->sameCompany($role);

        $permissions       = Permission::orderBy('module')->orderBy('action')->get()->groupBy('module');
        $rolePermissionIds = $role->permissions()->pluck('permissions.id')->toArray();

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

    public function update(Request $request, Role $role)
    {
        $this->authorize_permission('users', 'edit');
        $this->sameCompany($role);

        if ($role->is_system) {
            return back()->withErrors(['error' => 'System roles cannot be modified.']);
        }

        $companyId = auth()->user()->company_id;

        $validated = $request->validate([
            'name'         => [
                'required','string','max:100',
                Rule::unique('roles')->where(fn($q) => $q->where('company_id', $companyId))->ignore($role->id),
            ],
            'display_name' => 'nullable|string|max:100',
            'description'  => 'nullable|string|max:500',
            'permissions'  => 'nullable|array',
            'permissions.*'=> 'integer|exists:permissions,id',
        ]);

        $old = ['name' => $role->name, 'permissions' => $role->permissions()->pluck('id')->toArray()];

        $role->update([
            'name'         => $validated['name'],
            'display_name' => $validated['display_name'] ?? $validated['name'],
            'description'  => $validated['description'] ?? null,
        ]);

        $role->permissions()->sync($validated['permissions'] ?? []);

        AuditLog::record('update', 'roles', (string) $role->id, $old,
            ['name' => $role->name, 'permissions' => count($validated['permissions'] ?? [])],
            "Role updated: {$role->name}");

        return redirect()->route('admin.roles.index')
            ->with('success', "Role '{$role->name}' updated successfully.");
    }

    public function destroy(Role $role)
    {
        $this->authorize_permission('users', 'edit');
        $this->sameCompany($role);

        if ($role->is_system) {
            return back()->withErrors(['error' => 'System roles cannot be deleted.']);
        }
        if ($role->users()->count() > 0) {
            return back()->withErrors(['error' => 'Cannot delete a role that is assigned to users. Remove users first.']);
        }

        $name = $role->name;
        $role->permissions()->detach();
        $role->delete();

        AuditLog::record('delete', 'roles', null, ['name' => $name], null, "Role deleted: {$name}");

        return redirect()->route('admin.roles.index')->with('success', "Role '{$name}' deleted.");
    }

    // ── Helpers ───────────────────────────────────────────────────────────────
    private function authorize_permission(string $module, string $action): void
    {
        if (!auth()->user()->hasPermission($module, $action)) {
            abort(403, 'You do not have permission to perform this action.');
        }
    }

    private function sameCompany(Role $role): void
    {
        if ($role->company_id !== auth()->user()->company_id) {
            abort(403);
        }
    }
}
