/**
 * ECR(Engineering Change Request) 관련 테이블 idempotent 마이그레이션
 *
 *  - wace_plm 의 ECR_MNG / PRODUCT_MGMT / PART_MNG / COMM_CODE / USER_INFO 스키마와
 *    1:1 매칭되도록 컬럼 명세를 동기화 (CREATE TABLE IF NOT EXISTS + ADD COLUMN IF NOT EXISTS)
 *  - wace_plm 의 code_name(varchar) 함수도 그대로 재현 (mapper SQL 에서 사용)
 *  - 시퀀스 seq_ecr_no 도 동일 보장
 *  - 부팅 시 1회 실행 (멱등)
 *
 *  주의: 데이터 자체의 import 는 WacePlmDataImportService (POST /api/wace-import/*) 가 담당.
 *        본 마이그레이션은 "동일 스키마" 보장만 한다.
 */
import { getPool } from "../database/db";
import { logger } from "../utils/logger";

const STATEMENTS: string[] = [
  // ────────────────────────────────────────────────────────────────────────────
  // 1) ECR_MNG  (wace_plm dbexport 기준 컬럼 명세와 정확히 일치)
  //
  //   wace_plm DDL:
  //     objid integer NOT NULL, ecr_no varchar(100), product_objid integer,
  //     upg_no varchar(100), part_objid integer, request_cd varchar(100),
  //     title varchar(1000), writer varchar(100), status_cd varchar(100),
  //     before_contents varchar(4000), after_contents varchar(4000),
  //     reg_date timestamp, check_user_id varchar(100), check_date timestamp
  // ────────────────────────────────────────────────────────────────────────────
  `CREATE TABLE IF NOT EXISTS ecr_mng (
     objid           BIGINT PRIMARY KEY,
     ecr_no          VARCHAR(100),
     product_objid   BIGINT,
     upg_no          VARCHAR(100),
     part_objid      BIGINT,
     request_cd      VARCHAR(100),
     title           VARCHAR(1000),
     writer          VARCHAR(100),
     status_cd       VARCHAR(100) DEFAULT '0000100',
     before_contents VARCHAR(4000),
     after_contents  VARCHAR(4000),
     reg_date        TIMESTAMP    DEFAULT NOW(),
     check_user_id   VARCHAR(100),
     check_date      TIMESTAMP
   )`,
  // 기존 환경(이전 마이그레이션으로 짧은 길이로 만들어진 경우)을 위해 컬럼 폭 확장 (멱등)
  `ALTER TABLE ecr_mng ALTER COLUMN ecr_no          TYPE VARCHAR(100)  USING ecr_no::VARCHAR(100)`,
  `ALTER TABLE ecr_mng ALTER COLUMN upg_no          TYPE VARCHAR(100)  USING upg_no::VARCHAR(100)`,
  `ALTER TABLE ecr_mng ALTER COLUMN request_cd      TYPE VARCHAR(100)  USING request_cd::VARCHAR(100)`,
  `ALTER TABLE ecr_mng ALTER COLUMN title           TYPE VARCHAR(1000) USING title::VARCHAR(1000)`,
  `ALTER TABLE ecr_mng ALTER COLUMN writer          TYPE VARCHAR(100)  USING writer::VARCHAR(100)`,
  `ALTER TABLE ecr_mng ALTER COLUMN status_cd       TYPE VARCHAR(100)  USING status_cd::VARCHAR(100)`,
  `ALTER TABLE ecr_mng ALTER COLUMN before_contents TYPE VARCHAR(4000) USING before_contents::VARCHAR(4000)`,
  `ALTER TABLE ecr_mng ALTER COLUMN after_contents  TYPE VARCHAR(4000) USING after_contents::VARCHAR(4000)`,
  `ALTER TABLE ecr_mng ALTER COLUMN check_user_id   TYPE VARCHAR(100)  USING check_user_id::VARCHAR(100)`,
  // 신규로 만든 환경에 company_code 가 떨어졌을 수 있어 제거 시도 없이 그냥 두되, 누락된 컬럼만 보충
  `ALTER TABLE ecr_mng ADD COLUMN IF NOT EXISTS upg_no        VARCHAR(100)`,
  `ALTER TABLE ecr_mng ADD COLUMN IF NOT EXISTS check_user_id VARCHAR(100)`,
  `ALTER TABLE ecr_mng ADD COLUMN IF NOT EXISTS check_date    TIMESTAMP`,

  `CREATE INDEX IF NOT EXISTS idx_ecr_mng_status   ON ecr_mng (status_cd)`,
  `CREATE INDEX IF NOT EXISTS idx_ecr_mng_writer   ON ecr_mng (writer)`,
  `CREATE INDEX IF NOT EXISTS idx_ecr_mng_reg_date ON ecr_mng (reg_date DESC)`,

  // ECR_NO 시퀀스 — wace_plm 도 동일하게 별도 SEQUENCE 사용
  `CREATE SEQUENCE IF NOT EXISTS seq_ecr_no START WITH 1 INCREMENT BY 1`,
  // wace_plm 운영본은 33 까지 발번되어 있음. 우리 seq 가 더 작으면 그 값까지 끌어올려서
  // 채번 충돌(ON CONFLICT 로 UPDATE 분기 타는 사고)을 방지.
  `SELECT setval('seq_ecr_no', GREATEST((SELECT last_value FROM seq_ecr_no), 33))`,

  // ────────────────────────────────────────────────────────────────────────────
  // 2) PRODUCT_MGMT  (wace_plm dbexport 컬럼 풀세트)
  // ────────────────────────────────────────────────────────────────────────────
  `CREATE TABLE IF NOT EXISTS product_mgmt (
     objid              BIGINT PRIMARY KEY,
     product_category   VARCHAR(100),
     product_type       VARCHAR(100),
     product_grade      VARCHAR(100),
     product_ton        VARCHAR(100),
     product_boom       VARCHAR(100),
     product_vehicle    VARCHAR(100),
     product_code       VARCHAR(100),
     production_flag    VARCHAR(100),
     regdate            TIMESTAMP,
     writer             VARCHAR(100),
     contents           TEXT,
     price              VARCHAR,
     product_name       VARCHAR,
     product_name_code  VARCHAR,
     note               VARCHAR
   )`,
  // 기존 좁은 컬럼이면 폭 확장
  `ALTER TABLE product_mgmt ALTER COLUMN product_code TYPE VARCHAR(100) USING product_code::VARCHAR(100)`,
  `ALTER TABLE product_mgmt ALTER COLUMN product_type TYPE VARCHAR(100) USING product_type::VARCHAR(100)`,
  `ALTER TABLE product_mgmt ALTER COLUMN writer       TYPE VARCHAR(100) USING writer::VARCHAR(100)`,
  // 누락 컬럼 보충 (이전 마이그레이션은 일부만 만들었음)
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS product_category  VARCHAR(100)`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS product_grade     VARCHAR(100)`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS product_ton       VARCHAR(100)`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS product_boom      VARCHAR(100)`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS product_vehicle   VARCHAR(100)`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS contents          TEXT`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS price             VARCHAR`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS product_name_code VARCHAR`,
  `ALTER TABLE product_mgmt ADD COLUMN IF NOT EXISTS note              VARCHAR`,
  `CREATE INDEX IF NOT EXISTS idx_product_mgmt_code ON product_mgmt (product_code)`,

  // ────────────────────────────────────────────────────────────────────────────
  // 3) PART_MNG  (wace_plm dbexport 컬럼 풀세트 — 50+ 컬럼)
  // ────────────────────────────────────────────────────────────────────────────
  `CREATE TABLE IF NOT EXISTS part_mng (
     objid                BIGINT PRIMARY KEY,
     product_mgmt_objid   VARCHAR(100),
     upg_no               VARCHAR(100),
     part_no              VARCHAR(100),
     part_name            VARCHAR(100),
     unit                 VARCHAR(50),
     qty                  VARCHAR(50),
     spec                 VARCHAR(100),
     material             VARCHAR(100),
     weight               VARCHAR(50),
     part_type            VARCHAR(100),
     remark               VARCHAR(1000),
     es_spec              VARCHAR(100),
     ms_spec              VARCHAR(100),
     change_option        VARCHAR(50),
     design_apply_point   VARCHAR(50),
     management_flag      VARCHAR(50),
     revision             VARCHAR(50),
     status               VARCHAR(30),
     reg_date             TIMESTAMP,
     edit_date            TIMESTAMP,
     writer               VARCHAR(30),
     is_last              VARCHAR(5),
     eo_no                VARCHAR,
     eo_temp              VARCHAR,
     excel_upload_seq     INTEGER,
     sourcing_code        VARCHAR,
     sub_material         VARCHAR(100),
     parent_part_no       VARCHAR,
     design_date          VARCHAR,
     eo_date              VARCHAR,
     deploy_date          TIMESTAMP,
     thickness            VARCHAR,
     width                VARCHAR,
     height               VARCHAR,
     out_diameter         VARCHAR,
     in_diameter          VARCHAR,
     length               VARCHAR,
     supply_code          VARCHAR,
     change_type          VARCHAR,
     contract_objid       VARCHAR,
     maker                VARCHAR,
     post_processing      VARCHAR,
     material_code        VARCHAR,
     code1                VARCHAR,
     code2                VARCHAR,
     code3                VARCHAR,
     code4                VARCHAR,
     code5                VARCHAR,
     major_category       VARCHAR,
     sub_category         VARCHAR,
     is_new               VARCHAR(5),
     is_longd             VARCHAR(5)
   )`,
  // 기존 part_mng 가 작은 스키마였다면 누락 컬럼 보충 (멱등 ADD COLUMN IF NOT EXISTS)
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS product_mgmt_objid VARCHAR(100)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS upg_no             VARCHAR(100)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS unit               VARCHAR(50)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS qty                VARCHAR(50)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS spec               VARCHAR(100)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS material           VARCHAR(100)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS weight             VARCHAR(50)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS remark             VARCHAR(1000)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS es_spec            VARCHAR(100)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS ms_spec            VARCHAR(100)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS change_option      VARCHAR(50)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS design_apply_point VARCHAR(50)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS management_flag    VARCHAR(50)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS revision           VARCHAR(50)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS reg_date           TIMESTAMP`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS edit_date          TIMESTAMP`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS is_last            VARCHAR(5)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS eo_no              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS eo_temp            VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS excel_upload_seq   INTEGER`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS sourcing_code      VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS sub_material       VARCHAR(100)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS parent_part_no     VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS design_date        VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS eo_date            VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS deploy_date        TIMESTAMP`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS thickness          VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS width              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS height             VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS out_diameter       VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS in_diameter        VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS length             VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS supply_code        VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS change_type        VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS contract_objid     VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS maker              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS post_processing    VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS material_code      VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS code1              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS code2              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS code3              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS code4              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS code5              VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS major_category     VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS sub_category       VARCHAR`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS is_new             VARCHAR(5)`,
  `ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS is_longd           VARCHAR(5)`,
  `CREATE INDEX IF NOT EXISTS idx_part_mng_no ON part_mng (part_no)`,

  // ────────────────────────────────────────────────────────────────────────────
  // 4) COMM_CODE  (wace_plm 명세 보충 — 우리 시스템은 이미 일부 컬럼만 가졌을 수 있음)
  // ────────────────────────────────────────────────────────────────────────────
  `ALTER TABLE comm_code ADD COLUMN IF NOT EXISTS id      VARCHAR(100)`,
  `ALTER TABLE comm_code ADD COLUMN IF NOT EXISTS code_cd VARCHAR(100)`,
  `ALTER TABLE comm_code ADD COLUMN IF NOT EXISTS ext_val VARCHAR(10)`,

  // ────────────────────────────────────────────────────────────────────────────
  // 5) USER_INFO  (wace_plm 의 USER_INFO 와 동일하게 만들지만, 우리 user 테이블과는 별도)
  //   - mapper SQL 이 USER_INFO 를 직접 참조 (writer_name, check_name 서브쿼리)
  //   - import 시 wace_plm.USER_INFO → 우리 user_info 에 그대로 적재
  // ────────────────────────────────────────────────────────────────────────────
  `CREATE TABLE IF NOT EXISTS user_info (
     sabun           VARCHAR(1024),
     user_id         VARCHAR(1024) PRIMARY KEY,
     user_password   VARCHAR(1024),
     user_name       VARCHAR(1024),
     user_name_eng   VARCHAR(1024),
     user_name_cn    VARCHAR(1024),
     dept_code       VARCHAR(1024),
     dept_name       VARCHAR(1024),
     position_code   VARCHAR(1024),
     position_name   VARCHAR(1024),
     email           VARCHAR(1024),
     tel             VARCHAR(1024),
     cell_phone      VARCHAR(1024),
     user_type       VARCHAR(1024),
     user_type_name  VARCHAR(1024),
     regdate         TIMESTAMP,
     data_type       VARCHAR(64),
     status          VARCHAR(32),
     end_date        TIMESTAMP,
     fax_no          VARCHAR,
     partner_objid   VARCHAR,
     rank            VARCHAR
   )`,

  // ────────────────────────────────────────────────────────────────────────────
  // 6) public.code_name(varchar) 함수
  //   wace_plm mapper 들이 ECR 등에서 `code_name(STATUS_CD)` 호출 — 동일 함수 정의
  // ────────────────────────────────────────────────────────────────────────────
  `CREATE OR REPLACE FUNCTION public.code_name(v_code_id varchar) RETURNS varchar
     LANGUAGE plpgsql AS $$
   DECLARE v_code_name varchar;
   BEGIN
     SELECT code_name INTO v_code_name FROM comm_code WHERE code_id = v_code_id LIMIT 1;
     RETURN v_code_name;
   END;
   $$`,

  // ────────────────────────────────────────────────────────────────────────────
  // 7) 공통코드 시드 — 0000090(설변요청) / 0000099(ECR상태)
  // ────────────────────────────────────────────────────────────────────────────
  `DO $$
   BEGIN
     IF NOT EXISTS (SELECT 1 FROM comm_code WHERE code_id='0000090') THEN
       INSERT INTO comm_code (objid, code_id, parent_code_id, code_name, sort_order, status, regdate, writer)
       VALUES (extract(epoch FROM now())::BIGINT, '0000090', NULL, '설변요청 코드', 0, 'active', NOW(), 'system-seed');
     END IF;
     IF NOT EXISTS (SELECT 1 FROM comm_code WHERE parent_code_id='0000090') THEN
       INSERT INTO comm_code (objid, code_id, parent_code_id, code_name, sort_order, status, regdate, writer) VALUES
         (extract(epoch FROM now())::BIGINT + 1, '0090001', '0000090', '설계오류', 1, 'active', NOW(), 'system-seed'),
         (extract(epoch FROM now())::BIGINT + 2, '0090002', '0000090', '품질개선', 2, 'active', NOW(), 'system-seed'),
         (extract(epoch FROM now())::BIGINT + 3, '0090003', '0000090', '원가절감', 3, 'active', NOW(), 'system-seed'),
         (extract(epoch FROM now())::BIGINT + 4, '0090004', '0000090', '고객요청', 4, 'active', NOW(), 'system-seed'),
         (extract(epoch FROM now())::BIGINT + 5, '0090005', '0000090', '법규대응', 5, 'active', NOW(), 'system-seed'),
         (extract(epoch FROM now())::BIGINT + 6, '0090006', '0000090', '부품단종', 6, 'active', NOW(), 'system-seed');
     END IF;
   END $$`,

  // 0000099 / 자식(0000100=작성중, 0000101=결재중, 0000107=반려, 0000102=적용완료) 는 wace_plm
  //   원본에 그대로 존재하므로 별도 시드하지 않는다 (wace_comm_code.sql 시드 로더가 처리).
  //   wace 가 미보유한 0000090(설변요청) 만 위에서 시드.

  // ────────────────────────────────────────────────────────────────────────────
  // 8) ECR 메뉴 활성화 (기존 menu_info 100045 정규화)
  // ────────────────────────────────────────────────────────────────────────────
  `UPDATE menu_info SET menu_url = '/COMPANY_16/ecr/ecr', status = 'active'
     WHERE objid = '100045' AND (menu_url IS NULL OR menu_url = '')`,
];

export async function ensureEcrTables(): Promise<void> {
  const pool = getPool();
  let success = 0;
  let failed = 0;

  for (const stmt of STATEMENTS) {
    try {
      await pool.query(stmt);
      success++;
    } catch (e: any) {
      failed++;
      logger.warn(`[ecrMigration] 실패 (계속 진행): ${e?.message?.slice(0, 200)}`);
    }
  }

  logger.info(`🌱 ECR 마이그레이션 완료: 성공 ${success}건 / 실패 ${failed}건`);
}
