-- Recovery: orphan AppUser cleanup.
--
-- Применяется один раз вручную на стейдже/проде после деплоя
-- AuthorizationController + SuperAdminOrganizationsController фиксов
-- (audit 2026-04-27 #1, #2, #7).
--
-- Что делает:
--   1. Находит users у которых OrganizationId указывает на отсутствующую
--      или архивированную организацию.
--   2. Деактивирует таких users (IsActive=false), сбрасывает OrganizationId.
--   3. Отзывает все OpenIddict refresh/access токены этих users
--      (Status='revoked') чтобы существующие сессии оборвались.
--
-- Идемпотентен: повторный запуск ничего не ломает.
-- Не удаляет данные — только статусы. Юзер при необходимости может
-- быть восстановлен ручным UPDATE users SET "IsActive"=true.

BEGIN;

WITH orphan_users AS (
    SELECT u."Id"
    FROM users u
    LEFT JOIN organizations o ON o."Id" = u."OrganizationId"
    WHERE u."IsActive" = true
      AND (
        u."OrganizationId" IS NULL
        OR o."Id" IS NULL
        OR o."IsArchived" = true
      )
      AND NOT EXISTS (
        -- Не трогаем SuperAdmin'ов — у них org=null это норма.
        SELECT 1
        FROM "AspNetUserRoles" ur
        JOIN roles r ON r."Id" = ur."RoleId"
        WHERE ur."UserId" = u."Id" AND r."NormalizedName" = 'SUPERADMIN'
      )
)
UPDATE users
   SET "IsActive" = false,
       "OrganizationId" = NULL
 WHERE "Id" IN (SELECT "Id" FROM orphan_users);

UPDATE "OpenIddictTokens" t
   SET "Status" = 'revoked'
 WHERE t."Status" = 'valid'
   AND t."Subject" IN (
        SELECT u."Id"::text FROM users u
        WHERE u."IsActive" = false
   );

COMMIT;
