-- =====================================================================
-- cupang_db 초기화 스크립트 (PostgreSQL) — 쿠팡 밀크런 모듈
-- =====================================================================
-- 멱등(idempotent): 여러 번 실행해도 안전. 기존 데이터를 삭제하지 않는다.
--
-- ⚠️ 실행 전 사용자 승인 + 백업 확인 필수. DROP/TRUNCATE 없음.
--
-- 실행 방법 (운영 PostgreSQL 컨테이너명: postgres-db):
--
--   1) DB / 역할 / 스키마 생성 (superuser 로 1회)
--      read -s -p "cupang_app password: " APP_PWD; echo
--      docker exec -i postgres-db psql -U postgres \
--          -v app_password="$APP_PWD" \
--          < scripts/sql/cupang_db_init.sql
--
--   2) main-app .env 에 연결 정보 등록
--      CUPANG_DB_URL=postgresql://cupang_app:<APP_PWD>@postgres-db:5432/cupang_db
--
--   3) main-app 재기동
--      cd /opt/www/main && docker compose up -d --build
--
-- 주의:
--   - 기존 DB 가 있으면 DROP 하지 않는다(CREATE DATABASE 는 미존재 시에만).
--   - 비밀번호는 절대 Git 에 커밋하지 않는다. psql -v 로만 전달.
--   - itemcode_db 는 이 스크립트가 건드리지 않는다(상품은 읽기 전용 참조).
-- =====================================================================

\set ON_ERROR_STOP on

-- DB 가 없을 때만 생성
SELECT 'CREATE DATABASE cupang_db ENCODING ''UTF8'' TEMPLATE template0'
WHERE NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = 'cupang_db')
\gexec

-- 앱 전용 로그인 역할 (expense_app 패턴과 동일)
SELECT 'CREATE ROLE cupang_app LOGIN PASSWORD ' || quote_literal(:'app_password')
WHERE NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'cupang_app')
\gexec

-- 항상 최신 비밀번호로 동기화
SELECT 'ALTER ROLE cupang_app WITH LOGIN PASSWORD ' || quote_literal(:'app_password')
\gexec

GRANT CONNECT ON DATABASE cupang_db TO cupang_app;

-- cupang_db 컨텍스트로 전환
\connect cupang_db

-- ── updated_at 자동 갱신 트리거 함수 (멱등: CREATE OR REPLACE) ──
CREATE OR REPLACE FUNCTION cupang_set_updated_at() RETURNS trigger AS $$
BEGIN
  NEW.updated_at := now();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- ════════════════════════════════════════════════════════════
-- 1) 입고센터
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS cupang_centers (
    id          BIGSERIAL   PRIMARY KEY,
    name        TEXT        NOT NULL UNIQUE,
    active      BOOLEAN     NOT NULL DEFAULT TRUE,
    sort_order  INTEGER     NOT NULL DEFAULT 0,
    created_at  TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at  TIMESTAMPTZ NOT NULL DEFAULT now()
);

DROP TRIGGER IF EXISTS trg_cupang_centers_updated ON cupang_centers;
CREATE TRIGGER trg_cupang_centers_updated
  BEFORE UPDATE ON cupang_centers
  FOR EACH ROW EXECUTE FUNCTION cupang_set_updated_at();

-- ════════════════════════════════════════════════════════════
-- 2) 박스 입수량 규칙
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS cupang_box_rules (
    id                    BIGSERIAL   PRIMARY KEY,
    product_code          TEXT        NOT NULL UNIQUE,
    product_name_snapshot TEXT,
    box_name              TEXT        NOT NULL DEFAULT '쿠팡박스',
    units_per_box         INTEGER     NOT NULL CHECK (units_per_box > 0),
    active                BOOLEAN     NOT NULL DEFAULT TRUE,
    memo                  TEXT        NOT NULL DEFAULT '',
    created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at            TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_cupang_box_rules_code ON cupang_box_rules (product_code);

DROP TRIGGER IF EXISTS trg_cupang_box_rules_updated ON cupang_box_rules;
CREATE TRIGGER trg_cupang_box_rules_updated
  BEFORE UPDATE ON cupang_box_rules
  FOR EACH ROW EXECUTE FUNCTION cupang_set_updated_at();

-- ════════════════════════════════════════════════════════════
-- 3) 출고 묶음 (헤더)
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS cupang_shipments (
    id                   BIGSERIAL   PRIMARY KEY,
    document_no          TEXT        UNIQUE,
    created_by           TEXT        NOT NULL,
    document_date        DATE        NOT NULL,
    ship_date            DATE        NOT NULL,
    center_arrival_date  DATE        NOT NULL,
    center_id            BIGINT      REFERENCES cupang_centers(id),
    center_name_snapshot TEXT        NOT NULL DEFAULT '',
    ship_method          TEXT        NOT NULL DEFAULT '택배',
    outbound_summary     TEXT        NOT NULL DEFAULT '',
    worker               TEXT        NOT NULL DEFAULT '',
    status               TEXT        NOT NULL DEFAULT '작성중',
    memo                 TEXT        NOT NULL DEFAULT '',
    created_at           TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at           TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_cupang_ship_doc_date    ON cupang_shipments (document_date);
CREATE INDEX IF NOT EXISTS idx_cupang_ship_ship_date   ON cupang_shipments (ship_date);
CREATE INDEX IF NOT EXISTS idx_cupang_ship_arr_date    ON cupang_shipments (center_arrival_date);
CREATE INDEX IF NOT EXISTS idx_cupang_ship_status      ON cupang_shipments (status);
CREATE INDEX IF NOT EXISTS idx_cupang_ship_center      ON cupang_shipments (center_id);

DROP TRIGGER IF EXISTS trg_cupang_shipments_updated ON cupang_shipments;
CREATE TRIGGER trg_cupang_shipments_updated
  BEFORE UPDATE ON cupang_shipments
  FOR EACH ROW EXECUTE FUNCTION cupang_set_updated_at();

-- ════════════════════════════════════════════════════════════
-- 4) 출고 라인
-- ════════════════════════════════════════════════════════════
CREATE TABLE IF NOT EXISTS cupang_shipment_lines (
    id                    BIGSERIAL   PRIMARY KEY,
    shipment_id           BIGINT      NOT NULL REFERENCES cupang_shipments(id) ON DELETE CASCADE,
    line_no               INTEGER     NOT NULL,
    product_code          TEXT        NOT NULL,
    product_name_snapshot TEXT        NOT NULL,
    quantity              INTEGER     NOT NULL CHECK (quantity > 0),
    box_rule_id           BIGINT      REFERENCES cupang_box_rules(id),
    units_per_box         INTEGER,
    calculated_boxes      INTEGER,
    remainder_units       INTEGER,
    manual_box_text       TEXT        NOT NULL DEFAULT '',
    memo                  TEXT        NOT NULL DEFAULT '',
    created_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at            TIMESTAMPTZ NOT NULL DEFAULT now(),
    UNIQUE (shipment_id, line_no)
);
CREATE INDEX IF NOT EXISTS idx_cupang_lines_shipment ON cupang_shipment_lines (shipment_id);
CREATE INDEX IF NOT EXISTS idx_cupang_lines_code     ON cupang_shipment_lines (product_code);

DROP TRIGGER IF EXISTS trg_cupang_lines_updated ON cupang_shipment_lines;
CREATE TRIGGER trg_cupang_lines_updated
  BEFORE UPDATE ON cupang_shipment_lines
  FOR EACH ROW EXECUTE FUNCTION cupang_set_updated_at();

-- ════════════════════════════════════════════════════════════
-- 5) 초기 입고센터 seed (멱등: ON CONFLICT DO NOTHING)
--    sort_order 는 목록 순서대로 부여.
-- ════════════════════════════════════════════════════════════
INSERT INTO cupang_centers (name, sort_order) VALUES
  ('대구3', 1), ('인천32', 2), ('이천1', 3), ('인천42', 4), ('인천26', 5),
  ('인천16', 6), ('인천28', 7), ('안성8', 8), ('천안8(RC)', 9), ('시흥2', 10),
  ('인천36', 11), ('MGMH5', 12), ('XRC10(RC)', 13), ('인천14', 14), ('경기광주5', 15),
  ('경기광주3', 16), ('XRC06(RC)', 17), ('용인1', 18), ('인천30', 19), ('마장1', 20),
  ('안성4', 21), ('대구6', 22), ('전라광주2', 23), ('창원1', 24), ('고양1', 25),
  ('동탄1', 26), ('이천4', 27), ('XRC09(RC)', 28)
ON CONFLICT (name) DO NOTHING;

-- ════════════════════════════════════════════════════════════
-- 6) 권한 (cupang_app: CRUD only)
-- ════════════════════════════════════════════════════════════
GRANT USAGE ON SCHEMA public TO cupang_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON
  cupang_centers, cupang_box_rules, cupang_shipments, cupang_shipment_lines
  TO cupang_app;
GRANT USAGE, SELECT ON ALL SEQUENCES IN SCHEMA public TO cupang_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO cupang_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT USAGE, SELECT ON SEQUENCES TO cupang_app;

SELECT 'cupang_db ready' AS status;
