-- ============================================
-- User Service Database Schema
-- Database: user_service_db
-- Version: 1.0.0
-- Description: 사용자 및 가게 정보 관리
-- ============================================

-- ============================================
-- 1. 데이터베이스 및 Extension 생성
-- ============================================

-- UUID 확장 활성화
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- ============================================
-- 2. 테이블 생성
-- ============================================

-- 2.1 users 테이블
-- 목적: 사용자(소상공인) 정보 관리
CREATE TABLE IF NOT EXISTS users (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    name VARCHAR(100) NOT NULL,
    phone_number VARCHAR(20) NOT NULL,
    email VARCHAR(255) NOT NULL,
    password_hash VARCHAR(255) NOT NULL,
    role VARCHAR(20) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
    last_login_at TIMESTAMP,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

    -- 제약조건
    CONSTRAINT uk_users_email UNIQUE (email),
    CONSTRAINT uk_users_phone_number UNIQUE (phone_number),
    CONSTRAINT ck_users_role CHECK (role IN ('OWNER', 'ADMIN')),
    CONSTRAINT ck_users_status CHECK (status IN ('ACTIVE', 'INACTIVE', 'LOCKED', 'WITHDRAWN'))
);

-- users 테이블 코멘트
COMMENT ON TABLE users IS '사용자(소상공인) 정보 테이블';
COMMENT ON COLUMN users.id IS '사용자 고유 식별자 (UUID)';
COMMENT ON COLUMN users.name IS '사용자 이름';
COMMENT ON COLUMN users.phone_number IS '전화번호 (중복 불가)';
COMMENT ON COLUMN users.email IS '이메일 (로그인 ID, 중복 불가)';
COMMENT ON COLUMN users.password_hash IS 'bcrypt 암호화된 비밀번호';
COMMENT ON COLUMN users.role IS '사용자 역할 (OWNER: 소상공인, ADMIN: 관리자)';
COMMENT ON COLUMN users.status IS '계정 상태 (ACTIVE: 활성, INACTIVE: 비활성, LOCKED: 잠김, WITHDRAWN: 탈퇴)';
COMMENT ON COLUMN users.last_login_at IS '최종 로그인 시각';
COMMENT ON COLUMN users.created_at IS '생성 시각';
COMMENT ON COLUMN users.updated_at IS '수정 시각';

-- 2.2 stores 테이블
-- 목적: 가게(매장) 정보 관리
CREATE TABLE IF NOT EXISTS stores (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    user_id UUID NOT NULL,
    name VARCHAR(200) NOT NULL,
    industry VARCHAR(100) NOT NULL,
    address VARCHAR(500) NOT NULL,
    business_hours TEXT,
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

    -- 제약조건
    CONSTRAINT uk_stores_user_id UNIQUE (user_id),
    CONSTRAINT fk_stores_user_id FOREIGN KEY (user_id)
        REFERENCES users(id)
        ON DELETE CASCADE
        ON UPDATE CASCADE
);

-- stores 테이블 코멘트
COMMENT ON TABLE stores IS '가게(매장) 정보 테이블';
COMMENT ON COLUMN stores.id IS '가게 고유 식별자 (UUID)';
COMMENT ON COLUMN stores.user_id IS '사용자 ID (FK, 1:1 관계)';
COMMENT ON COLUMN stores.name IS '가게 이름';
COMMENT ON COLUMN stores.industry IS '업종 (예: 음식점, 카페)';
COMMENT ON COLUMN stores.address IS '주소';
COMMENT ON COLUMN stores.business_hours IS '영업시간 정보';
COMMENT ON COLUMN stores.created_at IS '생성 시각';
COMMENT ON COLUMN stores.updated_at IS '수정 시각';

-- ============================================
-- 3. 인덱스 생성
-- ============================================

-- 3.1 users 테이블 인덱스
-- 로그인 조회 최적화
CREATE INDEX IF NOT EXISTS idx_users_email
    ON users(email);

-- 전화번호 중복 검증 최적화
CREATE INDEX IF NOT EXISTS idx_users_phone_number
    ON users(phone_number);

-- 활성 사용자 필터링 최적화
CREATE INDEX IF NOT EXISTS idx_users_status
    ON users(status);

-- 3.2 stores 테이블 인덱스
-- User-Store 조인 최적화
CREATE INDEX IF NOT EXISTS idx_stores_user_id
    ON stores(user_id);

-- 인덱스 코멘트
COMMENT ON INDEX idx_users_email IS '로그인 조회 성능 최적화';
COMMENT ON INDEX idx_users_phone_number IS '전화번호 중복 검증 최적화';
COMMENT ON INDEX idx_users_status IS '활성 사용자 필터링 최적화';
COMMENT ON INDEX idx_stores_user_id IS 'User-Store 조인 성능 최적화';

-- ============================================
-- 4. 트리거 생성 (updated_at 자동 갱신)
-- ============================================

-- 4.1 updated_at 갱신 함수 생성
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- 4.2 users 테이블 트리거
CREATE TRIGGER trigger_users_updated_at
    BEFORE UPDATE ON users
    FOR EACH ROW
    EXECUTE FUNCTION update_updated_at_column();

-- 4.3 stores 테이블 트리거
CREATE TRIGGER trigger_stores_updated_at
    BEFORE UPDATE ON stores
    FOR EACH ROW
    EXECUTE FUNCTION update_updated_at_column();

-- ============================================
-- 5. 초기 데이터 (Optional)
-- ============================================

-- 5.1 관리자 계정 (Optional - 개발/테스트용)
-- 비밀번호: admin123 (bcrypt 해시)
-- INSERT INTO users (id, name, phone_number, email, password_hash, role, status)
-- VALUES (
--     uuid_generate_v4(),
--     'System Admin',
--     '010-0000-0000',
--     'admin@kt-event.com',
--     '$2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewY5GyYCdOzHxKuK',
--     'ADMIN',
--     'ACTIVE'
-- );

-- ============================================
-- 6. 권한 설정
-- ============================================

-- 애플리케이션 사용자에게 권한 부여 (사용자명은 환경에 맞게 수정)
-- GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO user_service_app;
-- GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO user_service_app;

-- ============================================
-- 7. 통계 정보 갱신
-- ============================================

-- 쿼리 플래너를 위한 통계 정보 수집
ANALYZE users;
ANALYZE stores;

-- ============================================
-- 8. 스키마 버전 정보
-- ============================================

-- 스키마 버전 관리 테이블 (Flyway/Liquibase 사용 시 자동 생성됨)
-- CREATE TABLE IF NOT EXISTS schema_version (
--     installed_rank INT NOT NULL,
--     version VARCHAR(50),
--     description VARCHAR(200) NOT NULL,
--     type VARCHAR(20) NOT NULL,
--     script VARCHAR(1000) NOT NULL,
--     checksum INT,
--     installed_by VARCHAR(100) NOT NULL,
--     installed_on TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
--     execution_time INT NOT NULL,
--     success BOOLEAN NOT NULL,
--     PRIMARY KEY (installed_rank)
-- );

-- ============================================
-- 9. 검증 쿼리
-- ============================================

-- 테이블 생성 확인
SELECT
    table_name,
    table_type
FROM
    information_schema.tables
WHERE
    table_schema = 'public'
    AND table_name IN ('users', 'stores')
ORDER BY
    table_name;

-- 인덱스 생성 확인
SELECT
    tablename,
    indexname,
    indexdef
FROM
    pg_indexes
WHERE
    schemaname = 'public'
    AND tablename IN ('users', 'stores')
ORDER BY
    tablename, indexname;

-- 제약조건 확인
SELECT
    conname AS constraint_name,
    contype AS constraint_type,
    conrelid::regclass AS table_name
FROM
    pg_constraint
WHERE
    conrelid IN ('users'::regclass, 'stores'::regclass)
ORDER BY
    table_name, constraint_name;

-- ============================================
-- 10. 성능 튜닝 설정 (Optional)
-- ============================================

-- 테이블 통계 수집 비율 조정 (필요 시)
-- ALTER TABLE users SET (autovacuum_vacuum_scale_factor = 0.05);
-- ALTER TABLE stores SET (autovacuum_vacuum_scale_factor = 0.05);

-- 테이블 통계 수집 임계값 조정 (필요 시)
-- ALTER TABLE users SET (autovacuum_analyze_threshold = 50);
-- ALTER TABLE stores SET (autovacuum_analyze_threshold = 50);

-- ============================================
-- END OF SCHEMA
-- ============================================
