<?php
/**
 * SalonPro X - Role Management Controller
 * Manages user roles and their permissions
 */

namespace Modules\Roles\Controllers;

use core\Controller;
use core\Auth;
use core\Database;
use core\View;
use core\Session;
use core\Security;

class RoleController extends Controller
{
    /**
     * List all roles
     */
    public function index(): void
    {
        Auth::requirePermission('roles_view');

        $db = Database::getInstance();
        $roles = $db->table('roles')
            ->select('roles.*, (SELECT COUNT(*) FROM users WHERE role_id = roles.id) as user_count')
            ->orderBy('roles.id', 'ASC')
            ->get();

        $this->view('Roles/index', [
            'title' => 'Roles & Permissions',
            'roles' => $roles,
            'breadcrumb' => ['Roles' => url('roles')],
        ]);
    }

    /**
     * Show create role form
     */
    public function create(): void
    {
        Auth::requirePermission('roles_create');

        $db = Database::getInstance();
        $permissions = $db->table('permissions')
            ->orderBy('module', 'ASC')
            ->orderBy('name', 'ASC')
            ->get();

        $grouped = [];
        foreach ($permissions as $perm) {
            $grouped[$perm->module][] = $perm;
        }

        $this->view('Roles/create', [
            'title' => 'Create Role',
            'groupedPermissions' => $grouped,
            'breadcrumb' => [
                'Roles' => url('roles'),
                'Create' => url('roles/create'),
            ],
        ]);
    }

    /**
     * Store new role
     */
    public function store(): void
    {
        Auth::requirePermission('roles_create');

        if (!Security::validateCsrfToken($this->request->post(CSRF_TOKEN_NAME))) {
            Session::setAlert('danger', 'Invalid security token. Please try again.');
            $this->back();
            return;
        }

        $name = $this->request->post('name');
        $description = $this->request->post('description');
        $permissions = $this->request->post('permissions', []);

        if (empty($name)) {
            Session::setAlert('danger', 'Role name is required.');
            $this->back();
            return;
        }

        $db = Database::getInstance();
        $slug = strtolower(str_replace(' ', '-', $name));

        $existing = $db->table('roles')->where('slug', $slug)->first();
        if ($existing) {
            Session::setAlert('danger', 'Role with this name already exists.');
            $this->back();
            return;
        }

        $db->beginTransaction();
        try {
            $roleId = $db->table('roles')->insert([
                'name' => $name,
                'slug' => $slug,
                'description' => $description,
            ]);

            foreach ($permissions as $permId) {
                $db->table('role_permissions')->insert([
                    'role_id' => $roleId,
                    'permission_id' => (int)$permId,
                ]);
            }

            $db->commit();
            Auth::logActivity('role_create', 'Created role: ' . $name);
            Auth::bumpPermissionsVersion();
            Session::setAlert('success', 'Role created successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            Session::setAlert('danger', 'Failed to create role: ' . $e->getMessage());
        }

        $this->redirect(url('roles'));
    }

    /**
     * Show edit role form
     */
    public function edit(int $id): void
    {
        Auth::requirePermission('roles_edit');

        $db = Database::getInstance();
        $role = $db->table('roles')->find($id);

        if (!$role) {
            Session::setAlert('danger', 'Role not found.');
            $this->redirect(url('roles'));
            return;
        }

        $permissions = $db->table('permissions')
            ->orderBy('module', 'ASC')
            ->orderBy('name', 'ASC')
            ->get();

        $rolePerms = $db->table('role_permissions')
            ->where('role_id', $id)
            ->get();
        $rolePermIds = array_map(fn($rp) => $rp->permission_id, $rolePerms);

        $grouped = [];
        foreach ($permissions as $perm) {
            $grouped[$perm->module][] = $perm;
        }

        $this->view('Roles/edit', [
            'title' => 'Edit Role',
            'role' => $role,
            'groupedPermissions' => $grouped,
            'rolePermIds' => $rolePermIds,
            'breadcrumb' => [
                'Roles' => url('roles'),
                'Edit' => url('roles/edit/' . $id),
            ],
        ]);
    }

    /**
     * Update role
     */
    public function update(int $id): void
    {
        Auth::requirePermission('roles_edit');

        if (!Security::validateCsrfToken($this->request->post(CSRF_TOKEN_NAME))) {
            Session::setAlert('danger', 'Invalid security token. Please try again.');
            $this->back();
            return;
        }

        $name = $this->request->post('name');
        $description = $this->request->post('description');
        $permissions = $this->request->post('permissions', []);

        if (empty($name)) {
            Session::setAlert('danger', 'Role name is required.');
            $this->back();
            return;
        }

        $db = Database::getInstance();
        $role = $db->table('roles')->find($id);

        if (!$role) {
            Session::setAlert('danger', 'Role not found.');
            $this->redirect(url('roles'));
            return;
        }

        $db->beginTransaction();
        try {
            $db->table('roles')->where('id', $id)->update([
                'name' => $name,
                'description' => $description,
            ]);

            $db->table('role_permissions')->where('role_id', $id)->delete();

            foreach ($permissions as $permId) {
                $db->table('role_permissions')->insert([
                    'role_id' => $id,
                    'permission_id' => (int)$permId,
                ]);
            }

            $db->commit();
            Auth::logActivity('role_update', 'Updated role: ' . $name);
            Auth::bumpPermissionsVersion();
            Session::setAlert('success', 'Role updated successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            Session::setAlert('danger', 'Failed to update role: ' . $e->getMessage());
        }

        $this->redirect(url('roles'));
    }

    /**
     * Delete role
     */
    public function delete(int $id): void
    {
        Auth::requirePermission('roles_delete');

        if (!Security::validateCsrfToken($this->request->post(CSRF_TOKEN_NAME))) {
            Session::setAlert('danger', 'Invalid security token. Please try again.');
            $this->back();
            return;
        }

        $db = Database::getInstance();
        $role = $db->table('roles')->find($id);

        if (!$role) {
            Session::setAlert('danger', 'Role not found.');
            $this->redirect(url('roles'));
            return;
        }

        if ($role->is_system) {
            Session::setAlert('danger', 'System roles cannot be deleted.');
            $this->redirect(url('roles'));
            return;
        }

        $userCount = $db->table('users')->where('role_id', $id)->count();
        if ($userCount > 0) {
            Session::setAlert('danger', 'Cannot delete role with ' . $userCount . ' users assigned.');
            $this->redirect(url('roles'));
            return;
        }

        $db->beginTransaction();
        try {
            $db->table('role_permissions')->where('role_id', $id)->delete();
            $db->table('roles')->delete($id);
            $db->commit();

            Auth::logActivity('role_delete', 'Deleted role: ' . $role->name);
            Auth::bumpPermissionsVersion();
            Session::setAlert('success', 'Role deleted successfully.');
        } catch (\Throwable $e) {
            $db->rollback();
            Session::setAlert('danger', 'Failed to delete role: ' . $e->getMessage());
        }

        $this->redirect(url('roles'));
    }
}
