-- =============================================================================
-- migrate-super-individual-persons-bind.sql
-- 超级个体（有效 VIP）与 @人物 persons 对齐 — 数据侧「补绑」迁移
--
-- 说明：
--   1) 新建 persons 行依赖存客宝 API（ckb_plan_id / ckb_api_key），请勿用纯 SQL 硬插完整行。
--      未绑上的用户：部署 soul-api 后，在管理端「内容管理 → @列表」点刷新，由接口自动 ensurePersonForUser。
--   2) 本脚本只做安全场景：已有 @人物、user_id 为空，且「未绑定 person 的 VIP」里仅一人昵称与 person.name 一致时，写入 user_id。
--   3) 执行前请备份库；建议先只跑「第一节 SELECT」看缺口，再跑 UPDATE。
--   4) VIP 口径：is_vip = 1 且 vip_expire_date > NOW()（与 activeSuperIndividualUserIDs 主路径一致）。
-- =============================================================================

-- ---------------------------------------------------------------------------
-- 1) 缺口清单：有效 VIP，且没有任何 person.user_id 指向该用户
-- ---------------------------------------------------------------------------
SELECT
  u.id AS user_id,
  TRIM(u.nickname) AS nickname,
  u.vip_expire_date,
  u.is_vip
FROM users u
WHERE u.is_vip = 1
  AND u.vip_expire_date > NOW()
  AND NOT EXISTS (
    SELECT 1 FROM persons p WHERE p.user_id IS NOT NULL AND TRIM(p.user_id) <> '' AND p.user_id = u.id
  )
ORDER BY u.vip_sort ASC, u.vip_activated_at DESC, u.id;

-- ---------------------------------------------------------------------------
-- 2) 冲突检查：多个未绑定的 person 同名（本脚本不会自动处理，需人工合并或走 API）
-- ---------------------------------------------------------------------------
SELECT TRIM(p.name) AS name_norm, COUNT(*) AS unbound_count
FROM persons p
WHERE p.user_id IS NULL OR TRIM(p.user_id) = ''
GROUP BY TRIM(p.name)
HAVING COUNT(*) > 1;

-- ---------------------------------------------------------------------------
-- 3) 同名唯一补绑：未绑 person ↔ 有效 VIP（昵称一致），且该 VIP 尚无 person
--    MySQL 8+ / 5.7 均可用；user_id 列为空串时按未绑定处理
-- ---------------------------------------------------------------------------
UPDATE persons p
INNER JOIN users u
  ON TRIM(u.nickname) = TRIM(p.name)
 AND CHAR_LENGTH(TRIM(COALESCE(u.nickname, ''))) > 0
SET
  p.user_id = u.id,
  p.updated_at = NOW()
WHERE (p.user_id IS NULL OR TRIM(p.user_id) = '')
  AND u.is_vip = 1
  AND u.vip_expire_date > NOW()
  AND NOT EXISTS (
    SELECT 1 FROM persons px WHERE px.user_id = u.id
  )
  AND (
    SELECT COUNT(*)
    FROM persons p3
    WHERE TRIM(p3.name) = TRIM(p.name)
      AND (p3.user_id IS NULL OR TRIM(p3.user_id) = '')
  ) = 1;

-- ---------------------------------------------------------------------------
-- 4) 可选：将本次补绑且仍为「手工」来源的 VIP 行标为 vip_sync（与统一计划展示一致；按业务需要取消注释）
-- ---------------------------------------------------------------------------
-- UPDATE persons p
-- INNER JOIN users u ON p.user_id = u.id
-- SET p.person_source = 'vip_sync', p.updated_at = NOW()
-- WHERE u.is_vip = 1
--   AND u.vip_expire_date > NOW()
--   AND (p.person_source IS NULL OR p.person_source = '');

-- ---------------------------------------------------------------------------
-- 5) 执行后再跑第一节 SELECT，应只剩「无同名 person」的 VIP（须由线上 API 创建 person）
-- ---------------------------------------------------------------------------
