-- name: CreateRole :one
INSERT INTO roles (name, description, is_system)
VALUES ($1, $2, $3)
RETURNING *;

-- name: GetRoleByID :one
SELECT * FROM roles WHERE id = $1;

-- name: GetRoleByName :one
SELECT * FROM roles WHERE name = $1;

-- name: ListRoles :many
SELECT
    COUNT(*) OVER () AS total_count,
    id, name, description, is_system, created_at, updated_at
FROM roles
WHERE
    (sqlc.narg('query')::TEXT IS NULL OR name ILIKE '%' || sqlc.narg('query')::TEXT || '%')
    AND (sqlc.narg('is_system')::BOOLEAN IS NULL OR is_system = sqlc.narg('is_system')::BOOLEAN)
ORDER BY name
LIMIT sqlc.narg('limit')::INT
OFFSET sqlc.narg('offset')::INT;

-- name: UpdateRole :exec
UPDATE roles
SET name = $2, description = $3, updated_at = CURRENT_TIMESTAMP
WHERE id = $1 AND is_system = false;

-- name: DeleteRole :exec
DELETE FROM roles WHERE id = $1 AND is_system = false;

-- name: UpsertPermission :one
INSERT INTO permissions (key, name, description, group_name)
VALUES ($1, $2, $3, $4)
ON CONFLICT (key) DO UPDATE SET
    name = EXCLUDED.name,
    description = EXCLUDED.description,
    group_name = EXCLUDED.group_name
RETURNING *;

-- name: ListPermissions :many
SELECT * FROM permissions ORDER BY group_name, key;

-- name: ListPermissionGroups :many
SELECT DISTINCT group_name FROM permissions ORDER BY group_name;

-- name: AssignPermissionToRole :exec
INSERT INTO role_permissions (role_id, permission_id)
VALUES ($1, $2)
ON CONFLICT DO NOTHING;

-- name: RemovePermissionFromRole :exec
DELETE FROM role_permissions
WHERE role_id = $1 AND permission_id = $2;

-- name: SetRolePermissions :exec
DELETE FROM role_permissions WHERE role_id = $1;

-- name: GetRolePermissions :many
SELECT p.*
FROM permissions p
INNER JOIN role_permissions rp ON rp.permission_id = p.id
WHERE rp.role_id = $1
ORDER BY p.group_name, p.key;

-- name: GetAllRolesWithPermissions :many
SELECT r.id AS role_id, r.name AS role_name, p.key AS permission_key
FROM roles r
INNER JOIN role_permissions rp ON rp.role_id = r.id
INNER JOIN permissions p ON p.id = rp.permission_id
ORDER BY r.name, p.key;

-- name: GetPermissionByKey :one
SELECT * FROM permissions WHERE key = $1;

-- name: BulkAssignPermissionsToRole :exec
INSERT INTO role_permissions (role_id, permission_id)
SELECT $1, p.id FROM permissions p WHERE p.id = ANY($2::BIGINT[])
ON CONFLICT DO NOTHING;
