<?php
namespace Modules\Users\Models;

use Core\Model;

class RoleModel extends Model {
    protected $table = 'roles';

    public function getAllForOrg(?int $orgId): array {
        if ($orgId === null) {
            $roles = $this->query(
                "SELECT r.*, (SELECT COUNT(*) FROM user_roles ur WHERE ur.role_id = r.id) as user_count
                 FROM roles r ORDER BY r.is_system DESC, r.name ASC"
            );
        } else {
            $roles = $this->query(
                "SELECT r.*, (SELECT COUNT(*) FROM user_roles ur WHERE ur.role_id = r.id) as user_count
                 FROM roles r WHERE r.org_id = ? OR r.is_system = 1
                 ORDER BY r.is_system DESC, r.name ASC",
                [$orgId]
            );
        }
        foreach ($roles as &$role) {
            $modules = $this->query(
                "SELECT DISTINCT p.module FROM role_permissions rp INNER JOIN permissions p ON rp.permission_id = p.id WHERE rp.role_id = ?",
                [$role['id']]
            );
            $role['top_modules'] = array_column($modules, 'module');
        }
        unset($role);
        return $roles;
    }

    public function getRoleWithPermissions(int $roleId): ?array {
        $role = $this->find($roleId);
        if (!$role) {
            return null;
        }
        $perms = $this->query(
            "SELECT CONCAT(p.module, '.', p.action) as perm
             FROM role_permissions rp INNER JOIN permissions p ON rp.permission_id = p.id
             WHERE rp.role_id = ?",
            [$roleId]
        );
        $role['permissions'] = array_column($perms, 'perm');
        return $role;
    }

    public function getAllPermissions(): array {
        return $this->query("SELECT * FROM permissions ORDER BY module, action");
    }

    public function createRole(array $data, array $permissionStrings): int {
        $roleId = $this->create($data);
        $this->syncPermissions($roleId, $permissionStrings);
        return $roleId;
    }

    public function updateRole(int $roleId, array $data, array $permissionStrings): bool {
        $this->update($roleId, $data);
        return $this->syncPermissions($roleId, $permissionStrings);
    }

    private function syncPermissions(int $roleId, array $permissionStrings): bool {
        $this->execute("DELETE FROM role_permissions WHERE role_id = ?", [$roleId]);
        foreach ($permissionStrings as $permString) {
            [$module, $action] = array_pad(explode('.', $permString, 2), 2, null);
            if (!$module || !$action) {
                continue;
            }
            $perm = $this->queryOne("SELECT id FROM permissions WHERE module = ? AND action = ?", [$module, $action]);
            if ($perm) {
                $permId = (int)$perm['id'];
            } else {
                $stmt = $this->db->prepare("INSERT INTO permissions (module, action) VALUES (?, ?)");
                $stmt->execute([$module, $action]);
                $permId = (int)$this->db->lastInsertId();
            }
            $exists = $this->queryOne("SELECT id FROM role_permissions WHERE role_id = ? AND permission_id = ?", [$roleId, $permId]);
            if (!$exists) {
                $this->execute("INSERT INTO role_permissions (role_id, permission_id) VALUES (?, ?)", [$roleId, $permId]);
            }
        }
        return true;
    }

    public function getUsersWithRole(int $roleId): array {
        return $this->query(
            "SELECT u.* FROM user_roles ur INNER JOIN users u ON ur.user_id = u.id WHERE ur.role_id = ?",
            [$roleId]
        );
    }

    public function deleteRole(int $roleId): bool {
        return $this->execute("DELETE FROM roles WHERE id = ? AND is_system = 0", [$roleId]);
    }
}
