BEGIN;

-- ============================================================================
-- RAG 公共知识库未归属默认项迁移
--
-- 背景：
--   历史 RAG 知识库存在 tenant_code 为空、area 为空/default/公共、is_public=true 的公共知识库。
--   如果这类记录是默认知识库，后端会禁止直接取消默认/删除；同时 PUBLIC 组另有默认
--   时，页面会出现两个“默认”，但它们属于不同默认组。
--
-- 目标：
--   1. 将历史未归属公共 RAG 知识库迁移到 tenant_code='PUBLIC'、area='公共'
--   2. 同步其关联 rag_chat_app 的 tenant_code/area
--   3. 迁移后 PUBLIC 组只保留一个默认知识库/默认应用
--
-- 执行前：
--   先执行 precheck_rag_public_orphan_defaults.sql，确认候选记录符合预期。
-- ============================================================================

ALTER TABLE public.rag_dataset
    ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64);

ALTER TABLE public.rag_chat_app
    ADD COLUMN IF NOT EXISTS tenant_code VARCHAR(64);

CREATE INDEX IF NOT EXISTS idx_rag_dataset_tenant_code
    ON public.rag_dataset(tenant_code)
    WHERE deleted_at IS NULL;

CREATE INDEX IF NOT EXISTS idx_rag_chat_app_tenant_code
    ON public.rag_chat_app(tenant_code)
    WHERE deleted_at IS NULL;

CREATE TEMP TABLE tmp_rag_public_orphan_dataset_ids (
    id BIGINT PRIMARY KEY
) ON COMMIT DROP;

INSERT INTO tmp_rag_public_orphan_dataset_ids (id)
SELECT d.id
FROM public.rag_dataset d
WHERE d.deleted_at IS NULL
  AND (d.tenant_code IS NULL OR BTRIM(d.tenant_code) = '')
  AND d.is_public IS TRUE
  AND (
      d.area IS NULL
      OR BTRIM(d.area) = ''
      OR LOWER(BTRIM(d.area)) = 'default'
      OR BTRIM(d.area) = '公共'
  )
ON CONFLICT (id) DO NOTHING;

WITH
updated_dataset AS (
    UPDATE public.rag_dataset d
    SET tenant_code = 'PUBLIC',
        area = '公共',
        is_public = TRUE,
        updated_at = NOW()
    FROM tmp_rag_public_orphan_dataset_ids orphan
    WHERE d.id = orphan.id
    RETURNING d.id
)
UPDATE public.rag_chat_app a
SET tenant_code = 'PUBLIC',
    area = '公共',
    updated_at = NOW()
FROM updated_dataset ud
WHERE a.dataset_id = ud.id
  AND a.deleted_at IS NULL;

WITH ranked_public_dataset AS (
    SELECT
        d.id,
        ROW_NUMBER() OVER (
            ORDER BY
                d.is_default DESC,
                CASE WHEN orphan.id IS NULL THEN 0 ELSE 1 END,
                d.created_at DESC,
                d.id DESC
        ) AS keep_default_rank
    FROM public.rag_dataset d
    LEFT JOIN tmp_rag_public_orphan_dataset_ids orphan ON orphan.id = d.id
    WHERE d.deleted_at IS NULL
      AND BTRIM(COALESCE(d.tenant_code, '')) = 'PUBLIC'
),
normalized_public_dataset AS (
    UPDATE public.rag_dataset d
    SET is_default = (rpd.keep_default_rank = 1),
        updated_at = NOW()
    FROM ranked_public_dataset rpd
    WHERE d.id = rpd.id
    RETURNING d.id, d.is_default
)
UPDATE public.rag_chat_app a
SET is_default = npd.is_default,
    tenant_code = 'PUBLIC',
    area = '公共',
    updated_at = NOW()
FROM normalized_public_dataset npd
WHERE a.dataset_id = npd.id
  AND a.deleted_at IS NULL;

-- 验收输出：PUBLIC 组当前默认知识库应只剩 1 条。
SELECT
    COUNT(*) FILTER (WHERE is_default = TRUE) AS public_default_count,
    COUNT(*) AS public_dataset_count
FROM public.rag_dataset
WHERE deleted_at IS NULL
  AND BTRIM(COALESCE(tenant_code, '')) = 'PUBLIC';

SELECT
    id,
    name,
    area,
    tenant_code,
    is_public,
    is_default,
    CASE
        WHEN id IN (SELECT id FROM tmp_rag_public_orphan_dataset_ids) THEN 'migrated_orphan'
        ELSE 'existing_public'
    END AS source_scope,
    created_at,
    updated_at
FROM public.rag_dataset
WHERE deleted_at IS NULL
  AND BTRIM(COALESCE(tenant_code, '')) = 'PUBLIC'
ORDER BY is_default DESC, created_at DESC, id DESC;

COMMIT;
