-- WING-OPS Database Schema: Auth Tables
-- auth 스키마 9개 테이블 (인증/인가/감사)

-- ============================================================
-- 1. auth_role — 역할 (FK 없음, 최상위)
-- ============================================================
CREATE TABLE auth.auth_role (
    role_sn integer NOT NULL,
    role_cd character varying(20) NOT NULL,
    role_nm character varying(50) NOT NULL,
    role_dc character varying(200),
    dflt_yn character(1) DEFAULT 'N'::bpchar NOT NULL,
    reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT pk_auth_role PRIMARY KEY (role_sn),
    CONSTRAINT uk_auth_role_cd UNIQUE (role_cd),
    CONSTRAINT ck_auth_role_dflt CHECK ((dflt_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);

CREATE SEQUENCE auth.auth_role_role_sn_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER SEQUENCE auth.auth_role_role_sn_seq OWNED BY auth.auth_role.role_sn;
ALTER TABLE ONLY auth.auth_role ALTER COLUMN role_sn SET DEFAULT nextval('auth.auth_role_role_sn_seq'::regclass);


-- ============================================================
-- 2. auth_org — 조직 (자기참조 FK)
-- ============================================================
CREATE TABLE auth.auth_org (
    org_sn integer NOT NULL,
    org_nm character varying(100) NOT NULL,
    org_abbr_nm character varying(20) NOT NULL,
    org_tp_cd character varying(20) NOT NULL,
    upper_org_sn integer,
    reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT pk_auth_org PRIMARY KEY (org_sn)
);

CREATE SEQUENCE auth.auth_org_org_sn_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER SEQUENCE auth.auth_org_org_sn_seq OWNED BY auth.auth_org.org_sn;
ALTER TABLE ONLY auth.auth_org ALTER COLUMN org_sn SET DEFAULT nextval('auth.auth_org_org_sn_seq'::regclass);


-- ============================================================
-- 3. auth_user — 사용자 (FK: auth_org)
-- ============================================================
CREATE TABLE auth.auth_user (
    user_id uuid DEFAULT public.uuid_generate_v4() NOT NULL,
    user_acnt character varying(50) NOT NULL,
    pswd_hash character varying(255),
    user_nm character varying(50) NOT NULL,
    rnkp_nm character varying(30),
    org_sn integer,
    user_stts_cd character varying(20) DEFAULT 'ACTIVE'::character varying NOT NULL,
    fail_cnt integer DEFAULT 0 NOT NULL,
    last_login_dtm timestamp with time zone,
    reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
    mdfcn_dtm timestamp with time zone DEFAULT now() NOT NULL,
    oauth_provider character varying(20),
    oauth_sub character varying(255),
    email character varying(255),
    CONSTRAINT pk_auth_user PRIMARY KEY (user_id),
    CONSTRAINT uk_auth_user_acnt UNIQUE (user_acnt),
    CONSTRAINT ck_auth_user_stts CHECK (((user_stts_cd)::text = ANY (ARRAY[('ACTIVE'::character varying)::text, ('LOCKED'::character varying)::text, ('INACTIVE'::character varying)::text])))
);

-- 조건부 유니크 인덱스 (NULL 값 제외)
CREATE UNIQUE INDEX uk_auth_user_email ON auth.auth_user USING btree (email) WHERE (email IS NOT NULL);
CREATE UNIQUE INDEX uk_auth_user_oauth ON auth.auth_user USING btree (oauth_provider, oauth_sub) WHERE (oauth_provider IS NOT NULL);


-- ============================================================
-- 4. auth_user_role — 사용자-역할 매핑 (FK: auth_user, auth_role)
-- ============================================================
CREATE TABLE auth.auth_user_role (
    user_id uuid NOT NULL,
    role_sn integer NOT NULL,
    reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
    CONSTRAINT pk_auth_user_role PRIMARY KEY (user_id, role_sn)
);


-- ============================================================
-- 5. auth_perm_tree — 권한 트리 (자기참조 FK)
-- ============================================================
CREATE TABLE auth.auth_perm_tree (
    rsrc_cd character varying(50) NOT NULL,
    parent_cd character varying(50),
    rsrc_nm character varying(100) NOT NULL,
    rsrc_desc character varying(200),
    icon character varying(20),
    rsrc_level smallint DEFAULT 0 NOT NULL,
    sort_ord smallint DEFAULT 0 NOT NULL,
    use_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
    CONSTRAINT pk_perm_tree PRIMARY KEY (rsrc_cd)
);


-- ============================================================
-- 6. auth_perm — 역할별 권한 (FK: auth_role)
-- ============================================================
CREATE TABLE auth.auth_perm (
    perm_sn integer NOT NULL,
    role_sn integer NOT NULL,
    rsrc_cd character varying(50) NOT NULL,
    grant_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
    reg_dtm timestamp with time zone DEFAULT now() NOT NULL,
    oper_cd character varying(20) NOT NULL,
    CONSTRAINT pk_auth_perm PRIMARY KEY (perm_sn),
    CONSTRAINT uk_auth_perm UNIQUE (role_sn, rsrc_cd, oper_cd),
    CONSTRAINT ck_auth_perm_grant CHECK ((grant_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar]))),
    CONSTRAINT ck_auth_perm_oper CHECK (((oper_cd)::text = ANY (ARRAY[('READ'::character varying)::text, ('CREATE'::character varying)::text, ('UPDATE'::character varying)::text, ('DELETE'::character varying)::text, ('MANAGE'::character varying)::text, ('EXPORT'::character varying)::text])))
);

CREATE SEQUENCE auth.auth_perm_perm_sn_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER SEQUENCE auth.auth_perm_perm_sn_seq OWNED BY auth.auth_perm.perm_sn;
ALTER TABLE ONLY auth.auth_perm ALTER COLUMN perm_sn SET DEFAULT nextval('auth.auth_perm_perm_sn_seq'::regclass);


-- ============================================================
-- 7. auth_setting — 시스템 설정
-- ============================================================
CREATE TABLE auth.auth_setting (
    setting_key character varying(100) NOT NULL,
    setting_val text NOT NULL,
    setting_dc character varying(500),
    mdfcn_dtm timestamp without time zone DEFAULT now(),
    CONSTRAINT auth_setting_pkey PRIMARY KEY (setting_key)
);


-- ============================================================
-- 8. auth_login_hist — 로그인 이력 (FK: auth_user)
-- ============================================================
CREATE TABLE auth.auth_login_hist (
    hist_sn integer NOT NULL,
    user_id uuid NOT NULL,
    login_dtm timestamp with time zone DEFAULT now() NOT NULL,
    ip_addr character varying(45),
    user_agent character varying(500),
    success_yn character(1) DEFAULT 'Y'::bpchar NOT NULL,
    CONSTRAINT pk_auth_login_hist PRIMARY KEY (hist_sn),
    CONSTRAINT ck_alh_success CHECK ((success_yn = ANY (ARRAY['Y'::bpchar, 'N'::bpchar])))
);

CREATE SEQUENCE auth.auth_login_hist_hist_sn_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER SEQUENCE auth.auth_login_hist_hist_sn_seq OWNED BY auth.auth_login_hist.hist_sn;
ALTER TABLE ONLY auth.auth_login_hist ALTER COLUMN hist_sn SET DEFAULT nextval('auth.auth_login_hist_hist_sn_seq'::regclass);


-- ============================================================
-- 9. auth_audit_log — 감사 로그
-- ============================================================
CREATE TABLE auth.auth_audit_log (
    log_sn integer NOT NULL,
    user_id uuid,
    action_cd character varying(30) NOT NULL,
    action_dtl character varying(100),
    http_method character varying(10),
    crud_type character varying(10),
    req_url character varying(500),
    req_dtm timestamp with time zone DEFAULT now() NOT NULL,
    res_dtm timestamp with time zone,
    res_status smallint,
    res_size integer,
    ip_addr character varying(45),
    user_agent character varying(500),
    extra jsonb,
    CONSTRAINT pk_auth_audit_log PRIMARY KEY (log_sn)
);

CREATE SEQUENCE auth.auth_audit_log_log_sn_seq
    AS integer
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

ALTER SEQUENCE auth.auth_audit_log_log_sn_seq OWNED BY auth.auth_audit_log.log_sn;
ALTER TABLE ONLY auth.auth_audit_log ALTER COLUMN log_sn SET DEFAULT nextval('auth.auth_audit_log_log_sn_seq'::regclass);


-- ============================================================
-- FK 제약조건
-- ============================================================
ALTER TABLE ONLY auth.auth_org
    ADD CONSTRAINT fk_auth_org_upper FOREIGN KEY (upper_org_sn) REFERENCES auth.auth_org(org_sn);

ALTER TABLE ONLY auth.auth_user
    ADD CONSTRAINT fk_auth_user_org FOREIGN KEY (org_sn) REFERENCES auth.auth_org(org_sn);

ALTER TABLE ONLY auth.auth_user_role
    ADD CONSTRAINT fk_aur_user FOREIGN KEY (user_id) REFERENCES auth.auth_user(user_id) ON DELETE CASCADE;

ALTER TABLE ONLY auth.auth_user_role
    ADD CONSTRAINT fk_aur_role FOREIGN KEY (role_sn) REFERENCES auth.auth_role(role_sn) ON DELETE CASCADE;

ALTER TABLE ONLY auth.auth_perm_tree
    ADD CONSTRAINT fk_perm_tree_parent FOREIGN KEY (parent_cd) REFERENCES auth.auth_perm_tree(rsrc_cd);

ALTER TABLE ONLY auth.auth_perm
    ADD CONSTRAINT fk_ap_role FOREIGN KEY (role_sn) REFERENCES auth.auth_role(role_sn) ON DELETE CASCADE;

ALTER TABLE ONLY auth.auth_login_hist
    ADD CONSTRAINT fk_alh_user FOREIGN KEY (user_id) REFERENCES auth.auth_user(user_id) ON DELETE CASCADE;


-- ============================================================
-- 인덱스
-- ============================================================
CREATE INDEX idx_auth_user_org ON auth.auth_user USING btree (org_sn);
CREATE INDEX idx_auth_user_stts ON auth.auth_user USING btree (user_stts_cd);

CREATE INDEX idx_auth_perm_role ON auth.auth_perm USING btree (role_sn);
CREATE INDEX idx_auth_perm_rsrc ON auth.auth_perm USING btree (rsrc_cd);
CREATE INDEX idx_auth_perm_oper ON auth.auth_perm USING btree (oper_cd);

CREATE INDEX idx_perm_tree_parent ON auth.auth_perm_tree USING btree (parent_cd);

CREATE INDEX idx_auth_login_user ON auth.auth_login_hist USING btree (user_id);
CREATE INDEX idx_auth_login_dtm ON auth.auth_login_hist USING btree (login_dtm);

CREATE INDEX idx_audit_log_user ON auth.auth_audit_log USING btree (user_id);
CREATE INDEX idx_audit_log_action ON auth.auth_audit_log USING btree (action_cd);
CREATE INDEX idx_audit_log_dtm ON auth.auth_audit_log USING btree (req_dtm);
