-- ============================================================================
-- V001: 인증/조직/역할/로그인 이력 초기 스키마
-- ============================================================================

-- UUID 생성용 확장 (kcgaidb는 신규 DB이므로 한 번만 활성화)
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- ----------------------------------------------------------------------------
-- 조직 (계층 구조)
-- ----------------------------------------------------------------------------
CREATE TABLE kcg.auth_org (
    org_sn          BIGSERIAL PRIMARY KEY,
    org_nm          VARCHAR(100) NOT NULL,
    org_abbr_nm     VARCHAR(50),
    org_tp_cd       VARCHAR(20),                       -- HQ, REGIONAL, STATION, AGENCY
    upper_org_sn    BIGINT REFERENCES kcg.auth_org(org_sn),
    sort_ord        INT DEFAULT 0,
    use_yn          VARCHAR(1) NOT NULL DEFAULT 'Y',
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_auth_org_upper ON kcg.auth_org(upper_org_sn);

COMMENT ON TABLE kcg.auth_org IS '조직 (해양경찰청 본청/지방청/서/파출소 등)';

-- ----------------------------------------------------------------------------
-- 사용자
-- ----------------------------------------------------------------------------
CREATE TABLE kcg.auth_user (
    user_id         UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_acnt       VARCHAR(50) UNIQUE NOT NULL,        -- 로그인 ID
    pswd_hash       VARCHAR(255),                       -- BCrypt 해시 (PASSWORD provider 전용)
    user_nm         VARCHAR(100) NOT NULL,              -- 이름
    rnkp_nm         VARCHAR(50),                        -- 직급/계급
    email           VARCHAR(255),
    org_sn          BIGINT REFERENCES kcg.auth_org(org_sn),
    user_stts_cd    VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING/ACTIVE/LOCKED/INACTIVE/REJECTED
    fail_cnt        INT NOT NULL DEFAULT 0,
    last_login_dtm  TIMESTAMPTZ,
    -- 인증 방식 확장 (Phase 9: GPKI/SSO)
    auth_provider   VARCHAR(20) NOT NULL DEFAULT 'PASSWORD', -- PASSWORD/GPKI/SSO
    provider_sub    VARCHAR(255),                       -- GPKI DN 또는 SSO subject
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_auth_user_org ON kcg.auth_user(org_sn);
CREATE INDEX idx_auth_user_status ON kcg.auth_user(user_stts_cd);
CREATE INDEX idx_auth_user_provider ON kcg.auth_user(auth_provider, provider_sub);

COMMENT ON TABLE kcg.auth_user IS '사용자 계정';
COMMENT ON COLUMN kcg.auth_user.auth_provider IS '인증 방식: PASSWORD(자체) / GPKI(공무원 인증서) / SSO';

-- ----------------------------------------------------------------------------
-- 역할
-- ----------------------------------------------------------------------------
CREATE TABLE kcg.auth_role (
    role_sn         BIGSERIAL PRIMARY KEY,
    role_cd         VARCHAR(50) UNIQUE NOT NULL,        -- ADMIN, OPERATOR, ANALYST, VIEWER, FIELD
    role_nm         VARCHAR(100) NOT NULL,
    role_dc         TEXT,
    dflt_yn         VARCHAR(1) NOT NULL DEFAULT 'N',       -- 신규 사용자 자동 배정 여부
    builtin_yn      VARCHAR(1) NOT NULL DEFAULT 'N',       -- 내장 역할 (삭제 불가)
    created_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at      TIMESTAMPTZ NOT NULL DEFAULT now()
);

COMMENT ON TABLE kcg.auth_role IS '사용자 역할';

-- ----------------------------------------------------------------------------
-- 사용자-역할 매핑 (다대다)
-- ----------------------------------------------------------------------------
CREATE TABLE kcg.auth_user_role (
    user_id         UUID NOT NULL REFERENCES kcg.auth_user(user_id) ON DELETE CASCADE,
    role_sn         BIGINT NOT NULL REFERENCES kcg.auth_role(role_sn) ON DELETE CASCADE,
    granted_at      TIMESTAMPTZ NOT NULL DEFAULT now(),
    granted_by      UUID,
    PRIMARY KEY (user_id, role_sn)
);

CREATE INDEX idx_auth_user_role_role ON kcg.auth_user_role(role_sn);

-- ----------------------------------------------------------------------------
-- 로그인 이력
-- ----------------------------------------------------------------------------
CREATE TABLE kcg.auth_login_hist (
    hist_sn         BIGSERIAL PRIMARY KEY,
    user_id         UUID,
    user_acnt       VARCHAR(50),
    login_dtm       TIMESTAMPTZ NOT NULL DEFAULT now(),
    login_ip        VARCHAR(45),
    user_agent      TEXT,
    result          VARCHAR(20) NOT NULL,                -- SUCCESS, FAILED, LOCKED
    fail_reason     VARCHAR(255),
    auth_provider   VARCHAR(20)
);

CREATE INDEX idx_login_hist_user ON kcg.auth_login_hist(user_id, login_dtm DESC);
CREATE INDEX idx_login_hist_acnt ON kcg.auth_login_hist(user_acnt, login_dtm DESC);
CREATE INDEX idx_login_hist_dtm ON kcg.auth_login_hist(login_dtm DESC);
