-- ================================================================
-- WING 인증 시스템 데이터베이스 (wing_auth)
-- 공공데이터베이스 표준화 관리 매뉴얼(2021.06) 기준 적용
-- PostgreSQL 16
-- ================================================================

-- ============================================================
-- 1. 사용자 및 데이터베이스 생성
-- ============================================================
CREATE USER wing_auth WITH PASSWORD 'WingAuth!2026';
CREATE DATABASE wing_auth OWNER wing_auth;

-- wing_auth 데이터베이스로 전환
\c wing_auth

-- ============================================================
-- 2. 확장 설치
-- ============================================================
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS pgcrypto;

GRANT ALL ON SCHEMA public TO wing_auth;

-- ============================================================
-- 3. 조직 (AUTH_ORG)
-- ============================================================
CREATE TABLE AUTH_ORG (
  ORG_SN          SERIAL        NOT NULL,
  ORG_NM          VARCHAR(100)  NOT NULL,
  ORG_ABBR_NM     VARCHAR(20)   NOT NULL,
  ORG_TP_CD       VARCHAR(20)   NOT NULL,
  UPPER_ORG_SN    INTEGER,
  REG_DTM         TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  CONSTRAINT PK_AUTH_ORG PRIMARY KEY (ORG_SN),
  CONSTRAINT FK_AUTH_ORG_UPPER FOREIGN KEY (UPPER_ORG_SN) REFERENCES AUTH_ORG(ORG_SN)
);

COMMENT ON TABLE  AUTH_ORG IS '인증조직';
COMMENT ON COLUMN AUTH_ORG.ORG_SN       IS '조직순번';
COMMENT ON COLUMN AUTH_ORG.ORG_NM       IS '조직명';
COMMENT ON COLUMN AUTH_ORG.ORG_ABBR_NM  IS '조직약칭명';
COMMENT ON COLUMN AUTH_ORG.ORG_TP_CD    IS '조직유형코드 (HEADQUARTERS, REGIONAL, STATION, AGENCY)';
COMMENT ON COLUMN AUTH_ORG.UPPER_ORG_SN IS '상위조직순번';
COMMENT ON COLUMN AUTH_ORG.REG_DTM      IS '등록일시';


-- ============================================================
-- 4. 역할 (AUTH_ROLE)
-- ============================================================
CREATE TABLE AUTH_ROLE (
  ROLE_SN         SERIAL        NOT NULL,
  ROLE_CD         VARCHAR(20)   NOT NULL,
  ROLE_NM         VARCHAR(50)   NOT NULL,
  ROLE_DC         VARCHAR(200),
  DFLT_YN         CHAR(1)       NOT NULL DEFAULT 'N',
  REG_DTM         TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  CONSTRAINT PK_AUTH_ROLE PRIMARY KEY (ROLE_SN),
  CONSTRAINT UK_AUTH_ROLE_CD UNIQUE (ROLE_CD),
  CONSTRAINT CK_AUTH_ROLE_DFLT CHECK (DFLT_YN IN ('Y','N'))
);

COMMENT ON TABLE  AUTH_ROLE IS '인증역할';
COMMENT ON COLUMN AUTH_ROLE.ROLE_SN IS '역할순번';
COMMENT ON COLUMN AUTH_ROLE.ROLE_CD IS '역할코드 (ADMIN, MANAGER, USER, VIEWER)';
COMMENT ON COLUMN AUTH_ROLE.ROLE_NM IS '역할명';
COMMENT ON COLUMN AUTH_ROLE.ROLE_DC IS '역할설명';
COMMENT ON COLUMN AUTH_ROLE.DFLT_YN IS '기본여부 (Y:신규 사용자 기본 역할)';
COMMENT ON COLUMN AUTH_ROLE.REG_DTM IS '등록일시';


-- ============================================================
-- 5. 사용자 (AUTH_USER)
-- ============================================================
CREATE TABLE AUTH_USER (
  USER_ID         UUID          NOT NULL DEFAULT uuid_generate_v4(),
  USER_ACNT       VARCHAR(50)   NOT NULL,
  PSWD_HASH       VARCHAR(255)  NOT NULL,
  USER_NM         VARCHAR(50)   NOT NULL,
  RNKP_NM         VARCHAR(30),
  ORG_SN          INTEGER,
  USER_STTS_CD    VARCHAR(20)   NOT NULL DEFAULT 'PENDING',
  FAIL_CNT        INTEGER       NOT NULL DEFAULT 0,
  LAST_LOGIN_DTM  TIMESTAMPTZ,
  REG_DTM         TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  MDFCN_DTM       TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  CONSTRAINT PK_AUTH_USER PRIMARY KEY (USER_ID),
  CONSTRAINT UK_AUTH_USER_ACNT UNIQUE (USER_ACNT),
  CONSTRAINT FK_AUTH_USER_ORG FOREIGN KEY (ORG_SN) REFERENCES AUTH_ORG(ORG_SN),
  CONSTRAINT CK_AUTH_USER_STTS CHECK (USER_STTS_CD IN ('PENDING','ACTIVE','LOCKED','INACTIVE','REJECTED'))
);

COMMENT ON TABLE  AUTH_USER IS '인증사용자';
COMMENT ON COLUMN AUTH_USER.USER_ID        IS '사용자아이디 (UUID)';
COMMENT ON COLUMN AUTH_USER.USER_ACNT      IS '사용자계정 (로그인 ID)';
COMMENT ON COLUMN AUTH_USER.PSWD_HASH      IS '비밀번호해시 (bcrypt)';
COMMENT ON COLUMN AUTH_USER.USER_NM        IS '사용자명';
COMMENT ON COLUMN AUTH_USER.RNKP_NM        IS '직급명';
COMMENT ON COLUMN AUTH_USER.ORG_SN         IS '조직순번';
COMMENT ON COLUMN AUTH_USER.USER_STTS_CD   IS '사용자상태코드 (PENDING:승인대기, ACTIVE:활성, LOCKED:잠김, INACTIVE:비활성, REJECTED:거절)';
COMMENT ON COLUMN AUTH_USER.FAIL_CNT       IS '로그인실패횟수';
COMMENT ON COLUMN AUTH_USER.LAST_LOGIN_DTM IS '최종로그인일시';
COMMENT ON COLUMN AUTH_USER.REG_DTM        IS '등록일시';
COMMENT ON COLUMN AUTH_USER.MDFCN_DTM      IS '수정일시';


-- ============================================================
-- 6. 사용자-역할 매핑 (AUTH_USER_ROLE)
-- ============================================================
CREATE TABLE AUTH_USER_ROLE (
  USER_ID         UUID          NOT NULL,
  ROLE_SN         INTEGER       NOT NULL,
  REG_DTM         TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  CONSTRAINT PK_AUTH_USER_ROLE PRIMARY KEY (USER_ID, ROLE_SN),
  CONSTRAINT FK_AUR_USER FOREIGN KEY (USER_ID) REFERENCES AUTH_USER(USER_ID) ON DELETE CASCADE,
  CONSTRAINT FK_AUR_ROLE FOREIGN KEY (ROLE_SN) REFERENCES AUTH_ROLE(ROLE_SN) ON DELETE CASCADE
);

COMMENT ON TABLE  AUTH_USER_ROLE IS '사용자역할매핑';
COMMENT ON COLUMN AUTH_USER_ROLE.USER_ID IS '사용자아이디';
COMMENT ON COLUMN AUTH_USER_ROLE.ROLE_SN IS '역할순번';
COMMENT ON COLUMN AUTH_USER_ROLE.REG_DTM IS '등록일시';


-- ============================================================
-- 7. 역할별 권한 (AUTH_PERM)
-- ============================================================
CREATE TABLE AUTH_PERM (
  PERM_SN         SERIAL        NOT NULL,
  ROLE_SN         INTEGER       NOT NULL,
  RSRC_CD         VARCHAR(50)   NOT NULL,
  GRANT_YN        CHAR(1)       NOT NULL DEFAULT 'Y',
  REG_DTM         TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  CONSTRAINT PK_AUTH_PERM PRIMARY KEY (PERM_SN),
  CONSTRAINT FK_AP_ROLE FOREIGN KEY (ROLE_SN) REFERENCES AUTH_ROLE(ROLE_SN) ON DELETE CASCADE,
  CONSTRAINT UK_AUTH_PERM UNIQUE (ROLE_SN, RSRC_CD),
  CONSTRAINT CK_AUTH_PERM_GRANT CHECK (GRANT_YN IN ('Y','N'))
);

COMMENT ON TABLE  AUTH_PERM IS '역할별권한';
COMMENT ON COLUMN AUTH_PERM.PERM_SN  IS '권한순번';
COMMENT ON COLUMN AUTH_PERM.ROLE_SN  IS '역할순번';
COMMENT ON COLUMN AUTH_PERM.RSRC_CD  IS '리소스코드 (탭 ID: prediction, hns, rescue 등)';
COMMENT ON COLUMN AUTH_PERM.GRANT_YN IS '부여여부 (Y:허용, N:거부)';
COMMENT ON COLUMN AUTH_PERM.REG_DTM  IS '등록일시';


-- ============================================================
-- 8. 로그인 이력 (AUTH_LOGIN_HIST)
-- ============================================================
CREATE TABLE AUTH_LOGIN_HIST (
  HIST_SN         SERIAL        NOT NULL,
  USER_ID         UUID          NOT NULL,
  LOGIN_DTM       TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  IP_ADDR         VARCHAR(45),
  USER_AGENT      VARCHAR(500),
  SUCCESS_YN      CHAR(1)       NOT NULL DEFAULT 'Y',
  CONSTRAINT PK_AUTH_LOGIN_HIST PRIMARY KEY (HIST_SN),
  CONSTRAINT FK_ALH_USER FOREIGN KEY (USER_ID) REFERENCES AUTH_USER(USER_ID) ON DELETE CASCADE,
  CONSTRAINT CK_ALH_SUCCESS CHECK (SUCCESS_YN IN ('Y','N'))
);

COMMENT ON TABLE  AUTH_LOGIN_HIST IS '로그인이력';
COMMENT ON COLUMN AUTH_LOGIN_HIST.HIST_SN    IS '이력순번';
COMMENT ON COLUMN AUTH_LOGIN_HIST.USER_ID    IS '사용자아이디';
COMMENT ON COLUMN AUTH_LOGIN_HIST.LOGIN_DTM  IS '로그인일시';
COMMENT ON COLUMN AUTH_LOGIN_HIST.IP_ADDR    IS 'IP주소';
COMMENT ON COLUMN AUTH_LOGIN_HIST.USER_AGENT IS '유저에이전트';
COMMENT ON COLUMN AUTH_LOGIN_HIST.SUCCESS_YN IS '성공여부 (Y:성공, N:실패)';


-- ============================================================
-- 8-1. 시스템 설정 (AUTH_SETTING)
-- ============================================================
CREATE TABLE AUTH_SETTING (
  SETTING_KEY     VARCHAR(100)  NOT NULL,
  SETTING_VAL     VARCHAR(500)  NOT NULL,
  SETTING_DC      VARCHAR(200),
  MDFCN_DTM       TIMESTAMPTZ   NOT NULL DEFAULT NOW(),
  CONSTRAINT PK_AUTH_SETTING PRIMARY KEY (SETTING_KEY)
);

COMMENT ON TABLE  AUTH_SETTING IS '시스템설정';
COMMENT ON COLUMN AUTH_SETTING.SETTING_KEY IS '설정키';
COMMENT ON COLUMN AUTH_SETTING.SETTING_VAL IS '설정값';
COMMENT ON COLUMN AUTH_SETTING.SETTING_DC  IS '설정설명';
COMMENT ON COLUMN AUTH_SETTING.MDFCN_DTM   IS '수정일시';


-- ============================================================
-- 9. 인덱스
-- ============================================================
CREATE INDEX IDX_AUTH_USER_STTS      ON AUTH_USER      (USER_STTS_CD);
CREATE INDEX IDX_AUTH_USER_ORG       ON AUTH_USER      (ORG_SN);
CREATE INDEX IDX_AUTH_PERM_ROLE      ON AUTH_PERM      (ROLE_SN);
CREATE INDEX IDX_AUTH_PERM_RSRC      ON AUTH_PERM      (RSRC_CD);
CREATE INDEX IDX_AUTH_LOGIN_USER     ON AUTH_LOGIN_HIST (USER_ID);
CREATE INDEX IDX_AUTH_LOGIN_DTM      ON AUTH_LOGIN_HIST (LOGIN_DTM);


-- ============================================================
-- 10. 초기 데이터: 역할
-- ============================================================
INSERT INTO AUTH_ROLE (ROLE_CD, ROLE_NM, ROLE_DC, DFLT_YN) VALUES
('ADMIN',   '관리자',     '시스템 전체 관리 권한',           'N'),
('MANAGER', '운영자',     '운영 및 사용자 관리 권한',        'N'),
('USER',    '일반사용자', '기본 업무 기능 접근 권한',        'Y'),
('VIEWER',  '뷰어',       '조회 전용 접근 권한',            'N');


-- ============================================================
-- 11. 초기 데이터: 역할별 권한 (탭 접근 매트릭스)
-- ============================================================

-- ADMIN (ROLE_SN=1): 모든 탭 접근
INSERT INTO AUTH_PERM (ROLE_SN, RSRC_CD, GRANT_YN) VALUES
(1, 'prediction', 'Y'), (1, 'hns', 'Y'), (1, 'rescue', 'Y'),
(1, 'reports', 'Y'),    (1, 'aerial', 'Y'), (1, 'assets', 'Y'),
(1, 'scat', 'Y'),       (1, 'incidents', 'Y'), (1, 'board', 'Y'),
(1, 'weather', 'Y'),    (1, 'admin', 'Y');

-- MANAGER (ROLE_SN=2): admin 탭 제외
INSERT INTO AUTH_PERM (ROLE_SN, RSRC_CD, GRANT_YN) VALUES
(2, 'prediction', 'Y'), (2, 'hns', 'Y'), (2, 'rescue', 'Y'),
(2, 'reports', 'Y'),    (2, 'aerial', 'Y'), (2, 'assets', 'Y'),
(2, 'scat', 'Y'),       (2, 'incidents', 'Y'), (2, 'board', 'Y'),
(2, 'weather', 'Y'),    (2, 'admin', 'N');

-- USER (ROLE_SN=3): assets, admin 탭 제외
INSERT INTO AUTH_PERM (ROLE_SN, RSRC_CD, GRANT_YN) VALUES
(3, 'prediction', 'Y'), (3, 'hns', 'Y'), (3, 'rescue', 'Y'),
(3, 'reports', 'Y'),    (3, 'aerial', 'Y'), (3, 'assets', 'N'),
(3, 'scat', 'Y'),       (3, 'incidents', 'Y'), (3, 'board', 'Y'),
(3, 'weather', 'Y'),    (3, 'admin', 'N');

-- VIEWER (ROLE_SN=4): reports, assets, scat, admin 제외
INSERT INTO AUTH_PERM (ROLE_SN, RSRC_CD, GRANT_YN) VALUES
(4, 'prediction', 'Y'), (4, 'hns', 'Y'), (4, 'rescue', 'Y'),
(4, 'reports', 'N'),    (4, 'aerial', 'Y'), (4, 'assets', 'N'),
(4, 'scat', 'N'),       (4, 'incidents', 'Y'), (4, 'board', 'Y'),
(4, 'weather', 'Y'),    (4, 'admin', 'N');


-- ============================================================
-- 12. 초기 데이터: 조직
-- ============================================================
INSERT INTO AUTH_ORG (ORG_NM, ORG_ABBR_NM, ORG_TP_CD) VALUES
('해양경찰청',           '해경청',   'HEADQUARTERS'),
('남해지방해양경찰청',    '남해청',   'REGIONAL'),
('제주지방해양경찰청',    '제주청',   'REGIONAL'),
('여수해양경찰서',       '여수서',   'STATION'),
('서귀포해양경찰서',     '서귀포서', 'STATION'),
('제주해양경찰서',       '제주서',   'STATION');

UPDATE AUTH_ORG SET UPPER_ORG_SN = 1 WHERE ORG_SN IN (2, 3);
UPDATE AUTH_ORG SET UPPER_ORG_SN = 2 WHERE ORG_SN = 4;
UPDATE AUTH_ORG SET UPPER_ORG_SN = 3 WHERE ORG_SN IN (5, 6);


-- ============================================================
-- 13. 초기 데이터: 관리자 계정 (admin / admin1234)
-- ============================================================
INSERT INTO AUTH_USER (USER_ACNT, PSWD_HASH, USER_NM, RNKP_NM, ORG_SN, USER_STTS_CD)
VALUES ('admin', crypt('admin1234', gen_salt('bf', 10)), '관리자', '경정', 1, 'ACTIVE');

-- admin 사용자에 ADMIN 역할 할당
INSERT INTO AUTH_USER_ROLE (USER_ID, ROLE_SN)
SELECT USER_ID, 1 FROM AUTH_USER WHERE USER_ACNT = 'admin';


-- ============================================================
-- 14. 초기 데이터: 시스템 설정
-- ============================================================
INSERT INTO AUTH_SETTING (SETTING_KEY, SETTING_VAL, SETTING_DC) VALUES
('registration.auto-approve', 'true',  '신규 사용자 자동 승인 여부 (true: 즉시 ACTIVE, false: PENDING 대기)'),
('registration.default-role',  'true',  '신규 사용자에게 기본 역할(DFLT_YN=Y) 자동 할당 여부');


-- ============================================================
-- 15. 권한 부여
-- ============================================================
GRANT ALL ON ALL TABLES IN SCHEMA public TO wing_auth;
GRANT ALL ON ALL SEQUENCES IN SCHEMA public TO wing_auth;


-- ============================================================
-- 데이터베이스 코멘트
-- ============================================================
COMMENT ON DATABASE wing_auth IS 'WING 인증 시스템 - 사용자 인증, 역할, 권한 관리';
