-- V31 소유자 데이터 표준 — 킨텍스 테넌트 표준화 (소유자 지시 2026-07-12)
-- 목표: ① 테넌트 코드 'kintex' → 'KINTEX'(대문자) 재명명(마스터 + 전 tenant_id 데이터/기본값)
--       ② tenant_id를 복합 PK의 선두 컬럼으로 전환(PRIMARY KEY (tenant_id, id))
--       ③ 표준 선언: 신규 테넌트 소유 테이블은 생성 시부터 PRIMARY KEY (tenant_id, id) + DEFAULT 'KINTEX'.
-- 불변: V1~V30 파일 불변. 본 마이그레이션은 단일 트랜잭션(Flyway 기본) — 실패 시 전체 롤백.
-- 멱등: 전 단계 재실행 안전(존재 가드·복합 PK 스킵 가드·ON CONFLICT).
-- 하위호환: 기존 발급 JWT(tid='kintex')·X-Tenant-Id 소문자 입력은 백엔드에서 대문자 정규화 후 매칭(코드 정합 참조).

-- ============================================================================
-- 1) 테넌트 재명명 'kintex' → 'KINTEX' (마스터 + 전 tenant_id 보유 테이블 동적 스윕)
-- ============================================================================
DO $$
DECLARE
    r record;
BEGIN
    -- (a) 'KINTEX' 마스터 행 확보 — 기존 'kintex' 행 속성(domain/name/status/created_at) 복사, 없으면 기본값.
    INSERT INTO tenant (id, name, domain, status, created_at)
    SELECT 'KINTEX', name, domain, status, created_at
      FROM tenant WHERE id = 'kintex'
    ON CONFLICT (id) DO NOTHING;

    INSERT INTO tenant (id, name, domain, status)
    VALUES ('KINTEX', 'KINTEX', 'kintex.zioinfo.co.kr', 'active')
    ON CONFLICT (id) DO NOTHING;

    -- (b) tenant_id 컬럼을 보유한 모든 테이블(event·hall·app_user·booth_sale·approval 등)의
    --     데이터 재지정 + DEFAULT 'KINTEX' 전환 — information_schema 동적 스윕(향후 tenant_id 추가분 포함).
    FOR r IN
        SELECT table_name
          FROM information_schema.columns
         WHERE table_schema = 'public'
           AND column_name = 'tenant_id'
    LOOP
        EXECUTE format('UPDATE %I SET tenant_id = ''KINTEX'' WHERE tenant_id = ''kintex''', r.table_name);
        EXECUTE format('ALTER TABLE %I ALTER COLUMN tenant_id SET DEFAULT ''KINTEX''', r.table_name);
    END LOOP;

    -- (c) 레거시 'kintex' 마스터 행 제거(이제 무참조 — tenant는 FK 대상이 아님, V26 확인).
    DELETE FROM tenant WHERE id = 'kintex';
END $$;

-- ============================================================================
-- 2) 복합 PK 전환 (tenant_id 선두) — event·hall·app_user
--    절차: (a) 대상 테이블 id를 참조하는 FK를 pg_constraint에서 동적 수집·정의 보관 후 드롭
--          (b) 단일 PK(id) 드롭 → PK(tenant_id, id) 추가 → UNIQUE(id) 추가(단일 id 참조 FK 보존)
--          (c) 보관한 FK를 UNIQUE(id) 대상으로 재생성
--    가드: PK에 tenant_id가 이미 포함(복합)이면 스킵(재실행 안전).
-- ============================================================================
DO $$
DECLARE
    t            text;
    pk_name      text;
    is_composite boolean;
    fk           record;
BEGIN
    CREATE TEMP TABLE _kx_fk_bak (child text, conname text, def text) ON COMMIT DROP;

    FOREACH t IN ARRAY ARRAY['event', 'hall', 'app_user'] LOOP
        -- 이미 복합 PK(tenant_id 포함)면 스킵.
        SELECT EXISTS (
            SELECT 1
              FROM pg_constraint c
              JOIN pg_attribute a
                ON a.attrelid = c.conrelid AND a.attnum = ANY (c.conkey)
             WHERE c.conrelid = t::regclass
               AND c.contype = 'p'
               AND a.attname = 'tenant_id'
        ) INTO is_composite;

        IF is_composite THEN
            CONTINUE;
        END IF;

        -- 현재 PK 제약 이름.
        SELECT conname INTO pk_name
          FROM pg_constraint
         WHERE conrelid = t::regclass AND contype = 'p';

        -- (a) 이 테이블(id)을 참조하는 FK 정의 보관 후 드롭.
        TRUNCATE _kx_fk_bak;
        INSERT INTO _kx_fk_bak (child, conname, def)
        SELECT con.conrelid::regclass::text, con.conname, pg_get_constraintdef(con.oid)
          FROM pg_constraint con
         WHERE con.confrelid = t::regclass
           AND con.contype = 'f';

        FOR fk IN SELECT child, conname FROM _kx_fk_bak LOOP
            EXECUTE format('ALTER TABLE %s DROP CONSTRAINT %I', fk.child, fk.conname);
        END LOOP;

        -- (b) 단일 PK 드롭 → 복합 PK 추가 → UNIQUE(id) 추가.
        IF pk_name IS NOT NULL THEN
            EXECUTE format('ALTER TABLE %I DROP CONSTRAINT %I', t, pk_name);
        END IF;
        EXECUTE format('ALTER TABLE %I ADD PRIMARY KEY (tenant_id, id)', t);
        IF NOT EXISTS (
            SELECT 1 FROM pg_constraint
             WHERE conrelid = t::regclass AND conname = t || '_id_key'
        ) THEN
            EXECUTE format('ALTER TABLE %I ADD CONSTRAINT %I UNIQUE (id)', t, t || '_id_key');
        END IF;

        -- (c) 보관 FK 재생성(정의는 REFERENCES <t>(id) → 이제 UNIQUE(id) 대상).
        FOR fk IN SELECT child, conname, def FROM _kx_fk_bak LOOP
            EXECUTE format('ALTER TABLE %s ADD CONSTRAINT %I %s', fk.child, fk.conname, fk.def);
        END LOOP;
    END LOOP;
END $$;

-- ============================================================================
-- 3) 표준 선언(주석) — 신규 테넌트 소유 테이블 규약.
-- ============================================================================
COMMENT ON TABLE tenant IS
    '전시관(Venue) 테넌트 마스터 — 최상위 격리 스코프. KINTEX=테넌트 #1(표준 코드 대문자). '
    '표준: 신규 테넌트 소유 테이블은 생성 시부터 PRIMARY KEY (tenant_id, id) + tenant_id DEFAULT ''KINTEX''.';
COMMENT ON COLUMN event.tenant_id    IS '소속 테넌트 코드(선두 PK 컬럼). 표준 대문자 코드 — DEFAULT ''KINTEX''.';
COMMENT ON COLUMN hall.tenant_id     IS '소속 테넌트 코드(선두 PK 컬럼). 표준 대문자 코드 — DEFAULT ''KINTEX''.';
COMMENT ON COLUMN app_user.tenant_id IS '소속 테넌트 코드(선두 PK 컬럼). 표준 대문자 코드 — DEFAULT ''KINTEX''.';
