-- ============================================================
-- 마이그레이션 004: AUTH_PERM에 OPER_CD 컬럼 추가
-- 리소스 단일 권한 → 리소스 × 오퍼레이션(RCUD) 2차원 권한 모델
-- ============================================================

-- Step 1: OPER_CD 컬럼 추가 (기존 레코드는 'READ'로 설정)
ALTER TABLE AUTH_PERM ADD COLUMN IF NOT EXISTS OPER_CD VARCHAR(20) NOT NULL DEFAULT 'READ';
COMMENT ON COLUMN AUTH_PERM.OPER_CD IS '오퍼레이션코드 (READ, CREATE, UPDATE, DELETE, MANAGE, EXPORT)';

-- Step 2: UNIQUE 제약 변경 (ROLE_SN, RSRC_CD) → (ROLE_SN, RSRC_CD, OPER_CD)
--         INSERT 전에 변경해야 CUD 레코드 삽입 시 충돌 없음
ALTER TABLE AUTH_PERM DROP CONSTRAINT IF EXISTS UK_AUTH_PERM;
ALTER TABLE AUTH_PERM ADD CONSTRAINT UK_AUTH_PERM UNIQUE (ROLE_SN, RSRC_CD, OPER_CD);

-- Step 3: 기존 GRANT_YN='Y' 레코드를 CREATE/UPDATE/DELETE로 확장
--         (기존에 허용된 리소스는 RCUD 모두 허용하여 동작 보존)
INSERT INTO AUTH_PERM (ROLE_SN, RSRC_CD, OPER_CD, GRANT_YN)
SELECT ROLE_SN, RSRC_CD, 'CREATE', GRANT_YN
FROM AUTH_PERM WHERE OPER_CD = 'READ' AND GRANT_YN = 'Y'
ON CONFLICT DO NOTHING;

INSERT INTO AUTH_PERM (ROLE_SN, RSRC_CD, OPER_CD, GRANT_YN)
SELECT ROLE_SN, RSRC_CD, 'UPDATE', GRANT_YN
FROM AUTH_PERM WHERE OPER_CD = 'READ' AND GRANT_YN = 'Y'
ON CONFLICT DO NOTHING;

INSERT INTO AUTH_PERM (ROLE_SN, RSRC_CD, OPER_CD, GRANT_YN)
SELECT ROLE_SN, RSRC_CD, 'DELETE', GRANT_YN
FROM AUTH_PERM WHERE OPER_CD = 'READ' AND GRANT_YN = 'Y'
ON CONFLICT DO NOTHING;

-- Step 3-1: VIEWER(조회 전용) 역할의 CUD 레코드 제거
--           VIEWER는 READ만 허용, CUD 확장은 의미 없음
DELETE FROM AUTH_PERM
WHERE ROLE_SN = (SELECT ROLE_SN FROM AUTH_ROLE WHERE ROLE_CD = 'VIEWER')
  AND OPER_CD != 'READ';

-- Step 4: 기본값 제거 (신규 레코드는 반드시 OPER_CD 명시)
ALTER TABLE AUTH_PERM ALTER COLUMN OPER_CD DROP DEFAULT;

-- Step 5: CHECK 제약 추가 (확장 가능: MANAGE, EXPORT 포함)
DO $$ BEGIN
  ALTER TABLE AUTH_PERM ADD CONSTRAINT CK_AUTH_PERM_OPER
    CHECK (OPER_CD IN ('READ','CREATE','UPDATE','DELETE','MANAGE','EXPORT'));
EXCEPTION WHEN duplicate_object THEN NULL;
END $$;

-- Step 6: 인덱스
CREATE INDEX IF NOT EXISTS IDX_AUTH_PERM_OPER ON AUTH_PERM (OPER_CD);

-- 검증
SELECT ROLE_SN, OPER_CD, COUNT(*), STRING_AGG(GRANT_YN, '') as grants
FROM AUTH_PERM
GROUP BY ROLE_SN, OPER_CD
ORDER BY ROLE_SN, OPER_CD;
