<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\BaseController;
use App\Core\Request;
use App\Core\Response;
use App\Helpers\AjaxResponse;
use App\Models\RoleModel;
use App\Services\ActivityLogger;

final class RoleController extends BaseController
{
    public function index(Request $request): Response
    {
        $rows = (new RoleModel())->allWithUserCounts();

        if ($request->isAjax() || $request->isJson()) {
            return AjaxResponse::success($rows);
        }

        return $this->view('roles/index', [
            'title' => 'Roles & Permissions',
            'activeNav' => 'roles',
            'breadcrumbs' => [['Home', 'dashboard'], ['Administration', 'users'], ['Roles & Permissions', 'roles']],
            'roles' => $rows,
        ]);
    }

    public function store(Request $request): Response
    {
        $model = new RoleModel();

        $data = $this->validateOrFail($request, [
            'name' => 'required|string|max:100',
            'description' => 'nullable|string|max:255',
        ]);

        $slug = $this->slugify($data['name']);
        if ($model->slugTaken($slug)) {
            return AjaxResponse::validationError(['name' => ['A role with a similar name already exists.']]);
        }

        $id = $model->insert(['name' => $data['name'], 'slug' => $slug, 'description' => $data['description'] ?? null, 'is_system' => 0]);
        ActivityLogger::record('role', $id, 'role_created', "Created role \"{$data['name']}\"", category: 'admin');

        return AjaxResponse::created($model->find($id), 'Role created.');
    }

    public function update(Request $request, array $params): Response
    {
        $model = new RoleModel();
        $roleId = (int) $params['id'];

        $data = $this->validateOrFail($request, [
            'name' => 'required|string|max:100',
            'description' => 'nullable|string|max:255',
        ]);

        $model->update($roleId, $data);
        ActivityLogger::record('role', $roleId, 'role_updated', "Updated role \"{$data['name']}\"", category: 'admin');

        return AjaxResponse::success($model->find($roleId), 'Role updated.');
    }

    public function destroy(Request $request, array $params): Response
    {
        $model = new RoleModel();
        $roleId = (int) $params['id'];

        if (!$model->canBeDeleted($roleId)) {
            return AjaxResponse::error('This role cannot be deleted — it is either a system role or still assigned to users.', 422);
        }

        $model->delete($roleId);
        ActivityLogger::record('role', $roleId, 'role_deleted', 'Role deleted', category: 'admin');

        return AjaxResponse::success(null, 'Role deleted.');
    }

    private function slugify(string $name): string
    {
        $slug = strtolower(trim($name));
        $slug = preg_replace('/[^a-z0-9]+/', '_', $slug) ?? $slug;

        return trim($slug, '_');
    }
}
