// ============================================================
// 프로젝트관리 > 진행관리 (wace_plm 도메인 이식)
// 메인 화면: wace `/project/projectMgmtWbsList3.do` (= 운영판 RPS 진행관리)
// 그리드 SQL: wace_plm/src/com/pms/mapper/project.xml:3854 projectMgmtWbsGridList
// JSP 원본: wace_plm/WebContent/WEB-INF/view/project/projectMgmtWbsList3.jsp
//
// 1:1 이식 + RPS 매핑 변경:
//   · wace의 CLIENT_MNG/SUPPLY_MNG CASE WHEN LIKE 'C_%' 분기 → RPS는 customer_mng 단일 LEFT JOIN
//   · CODE_NAME() 함수는 RPS DB 보유 — 그대로 사용
//   · PMS_WBS_TASK/SETUP_WBS_TASK 의존 컬럼은 그리드 표시 컬럼에 없으므로 미반영 (P2)
// ============================================================

import { getPool } from "../database/db";
import { logger } from "../utils/logger";

export interface ProgressListFilter {
  Year?: string;                    // 년도 (TO_CHAR(REGDATE,'YYYY'))
  project_nos?: string;             // wace project_nos (쉼표 직렬화 OBJID — 다중 또는 단일)
  category_cd?: string;
  customer_objid?: string;
  product?: string;
  status_cd?: string;
  result_cd?: string;
  contract_start_date?: string;     // 요청납기 시작
  contract_end_date?: string;       // 요청납기 끝
  area_cd?: string;                 // '국내'/'해외' 라벨로 비교 (wace 1:1)
  free_of_charge?: string;          // '유상'/'무상' 라벨로 비교
  // 영업관리 패턴(search_partObjId 단일) 통일 — wace의 product_item_code/_name LIKE 두 필드는 부재화
  search_partObjId?: string;        // part_mng.objid::varchar = project_mgmt.part_objid
  serial_no?: string;               // contract_item_serial EXISTS
  pm_user_id?: string;              // (검색폼 주석처리되어 있으나 SQL은 받음)
  location?: string;
  setup?: string;
}

// ─── 목록: 운영판 projectMgmtWbsGridList 1:1 ──────────────────

export async function listProgress(filter: ProgressListFilter) {
  const pool = getPool();
  const conditions: string[] = [];
  const params: any[] = [];
  let idx = 1;

  // wace L4187: Year — TO_CHAR(REGDATE,'YYYY')
  if (filter.Year) {
    conditions.push(`TO_CHAR(T.REGDATE,'YYYY') = $${idx++}`);
    params.push(filter.Year);
  }

  // wace L4195: project_nos 쉼표 split → OBJID IN
  if (filter.project_nos) {
    const list = filter.project_nos.split(",").map(s => s.trim()).filter(Boolean);
    if (list.length > 0) {
      const placeholders = list.map(() => `$${idx++}`).join(",");
      conditions.push(`T.OBJID IN (${placeholders})`);
      params.push(...list);
    }
  }

  if (filter.category_cd) { conditions.push(`T.CATEGORY_CD = $${idx++}`); params.push(filter.category_cd); }
  if (filter.customer_objid) { conditions.push(`T.CUSTOMER_OBJID = $${idx++}`); params.push(filter.customer_objid); }
  if (filter.product) { conditions.push(`T.PRODUCT = $${idx++}`); params.push(filter.product); }
  if (filter.status_cd) { conditions.push(`T.STATUS_CD = $${idx++}`); params.push(filter.status_cd); }
  if (filter.result_cd) { conditions.push(`T.RESULT_CD = $${idx++}`); params.push(filter.result_cd); }

  // wace L4224-4237: 요청납기 범위 — COALESCE(contract_item.due_date, project_mgmt.due_date, contract_mgmt.due_date)
  const dueDateCoalesce = `COALESCE(
    (SELECT CI.DUE_DATE FROM contract_item CI WHERE CI.contract_objid = T.CONTRACT_OBJID AND CI.part_objid = T.PART_OBJID AND CI.status = 'ACTIVE' ORDER BY CI.objid DESC LIMIT 1),
    T.DUE_DATE,
    (SELECT CM.due_date FROM contract_mgmt CM WHERE CM.OBJID = T.CONTRACT_OBJID LIMIT 1)
  )`;
  if (filter.contract_start_date) {
    conditions.push(`TO_DATE(${dueDateCoalesce},'YYYY-MM-DD') >= TO_DATE($${idx++},'YYYY-MM-DD')`);
    params.push(filter.contract_start_date);
  }
  if (filter.contract_end_date) {
    conditions.push(`TO_DATE(${dueDateCoalesce},'YYYY-MM-DD') <= TO_DATE($${idx++},'YYYY-MM-DD')`);
    params.push(filter.contract_end_date);
  }

  if (filter.pm_user_id) { conditions.push(`T.PM_USER_ID = $${idx++}`); params.push(filter.pm_user_id); }
  if (filter.location) { conditions.push(`UPPER(T.LOCATION) LIKE UPPER($${idx++})`); params.push(`%${filter.location}%`); }
  if (filter.setup) { conditions.push(`UPPER(T.SETUP) LIKE UPPER($${idx++})`); params.push(`%${filter.setup}%`); }

  // wace L4249: area_cd — CODE_NAME(area_cd) 라벨 비교 ('국내'/'해외')
  if (filter.area_cd) {
    conditions.push(`CODE_NAME(T.AREA_CD) = $${idx++}`);
    params.push(filter.area_cd);
  }

  // wace L4253: free_of_charge — contract_mgmt.paid_type → '유상'/'무상' 매핑 비교
  if (filter.free_of_charge) {
    conditions.push(`(SELECT
        CASE
          WHEN O.PAID_TYPE = 'paid' THEN '유상'
          WHEN O.PAID_TYPE = 'free' THEN '무상'
          ELSE O.PAID_TYPE
        END
      FROM contract_mgmt AS O WHERE O.OBJID = T.CONTRACT_OBJID) = $${idx++}`);
    params.push(filter.free_of_charge);
  }

  // 영업관리 패턴 통일: search_partObjId 단일 (PartSelect의 part_mng.objid 값 매칭)
  // wace 매퍼는 product_item_code/_name LIKE 텍스트 검색이지만 RPS는 part_objid 직접 매칭.
  if (filter.search_partObjId) {
    conditions.push(`T.PART_OBJID = $${idx++}`);
    params.push(filter.search_partObjId);
  }
  // wace L4271: serial_no — EXISTS contract_item_serial
  if (filter.serial_no) {
    conditions.push(`EXISTS (
      SELECT 1 FROM contract_item_serial CIS
      WHERE CIS.item_objid::varchar = T.CONTRACT_ITEM_OBJID
        AND UPPER(CIS.status) = 'ACTIVE'
        AND UPPER(CIS.serial_no) LIKE UPPER($${idx++})
    )`);
    params.push(`%${filter.serial_no}%`);
  }

  const where = conditions.length ? `WHERE ${conditions.join(" AND ")}` : "";

  // wace projectMgmtWbsGridList 활성 본문 1:1 (그리드 표시 18셀 + 필수 부속)
  const sql = `
    SELECT
       T.OBJID
      ,T.CATEGORY_CD
      ,CODE_NAME(T.CATEGORY_CD) AS CATEGORY_NAME
      ,T.CUSTOMER_OBJID
      ,C.customer_name AS CUSTOMER_NAME
      ,T.PRODUCT
      ,CODE_NAME(T.PRODUCT) AS PRODUCT_NAME
      ,T.STATUS_CD
      ,CODE_NAME(T.STATUS_CD) AS STATUS_NAME
      ,T.RESULT_CD
      ,CODE_NAME(T.RESULT_CD) AS RESULT_NAME
      ,T.DUE_DATE
      ,T.LOCATION
      ,T.SETUP
      ,T.FACILITY
      ,CODE_NAME(T.FACILITY) AS FACILITY_NAME
      ,T.FACILITY_QTY
      ,T.FACILITY_TYPE
      ,T.FACILITY_DEPTH
      ,T.PROJECT_NO
      ,T.PM_USER_ID
      ,(SELECT user_name FROM user_info WHERE user_id = (SELECT pm_user_id FROM contract_mgmt WHERE OBJID = T.CONTRACT_OBJID)) AS PM_USER_NAME
      ,T.CONTRACT_PRICE
      ,T.CONTRACT_PRICE_CURRENCY
      ,T.CONTRACT_CURRENCY
      ,CODE_NAME(T.CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME
      ,(SELECT CM.exchange_rate FROM contract_mgmt CM WHERE CM.objid = T.CONTRACT_OBJID) AS EXCHANGE_RATE
      ,COALESCE(
         (SELECT CI.customer_request FROM contract_item CI
           WHERE CI.contract_objid = T.CONTRACT_OBJID AND CI.part_objid = T.PART_OBJID
             AND CI.status='ACTIVE' ORDER BY CI.objid DESC LIMIT 1),
         (SELECT CM.customer_request FROM contract_mgmt CM WHERE CM.objid = T.CONTRACT_OBJID)
       ) AS CUSTOMER_REQUEST
      ,(SELECT CODE_NAME(CI.return_reason) FROM contract_item CI
         WHERE CI.contract_objid = T.CONTRACT_OBJID AND CI.part_objid = T.PART_OBJID
           AND CI.status='ACTIVE' ORDER BY CI.objid DESC LIMIT 1) AS RETURN_REASON_NAME
      ,T.REGDATE
      ,TO_CHAR(T.REGDATE,'YYYY-MM-DD') AS REG_DATE
      ,T.WRITER
      ,(SELECT user_name FROM user_info WHERE user_id = T.WRITER) AS WRITER_NAME
      ,(SELECT COUNT(1) FROM attach_file_info WHERE target_objid = T.OBJID AND doc_type='contractMgmt01' AND UPPER(status)='ACTIVE') AS CU01_CNT
      ,(SELECT COUNT(1) FROM attach_file_info WHERE target_objid = T.OBJID AND doc_type='contractMgmt02' AND UPPER(status)='ACTIVE') AS CU02_CNT
      ,T.CONTRACT_NO
      ,T.CUSTOMER_EQUIP_NAME
      ,T.CONTRACT_DEL_DATE
      ,T.CONTRACT_COMPANY
      ,CODE_NAME(T.CONTRACT_COMPANY) AS CONTRACT_COMPANY_NAME
      ,T.CONTRACT_DATE
      ,T.PO_NO
      ,T.MANUFACTURE_PLANT
      ,CODE_NAME(T.MANUFACTURE_PLANT) AS MANUFACTURE_PLANT_NAME
      ,T.CONTRACT_RESULT
      ,CODE_NAME(T.CONTRACT_RESULT) AS CONTRACT_RESULT_NAME
      ,CODE_NAME(T.AREA_CD) AS AREA_NAME
      ,T.PROJECT_NAME

      -- 운영판 그리드 핵심 컬럼들
      ,(SELECT CASE
          WHEN O.PAID_TYPE = 'paid' THEN '유상'
          WHEN O.PAID_TYPE = 'free' THEN '무상'
          ELSE O.PAID_TYPE
        END
        FROM contract_mgmt AS O WHERE O.OBJID = T.CONTRACT_OBJID) AS FREE_OF_CHARGE
      ,COALESCE(NULLIF(T.QUANTITY,'')::numeric, 0) AS CONTRACT_QTY
      ,T.PART_NO AS PRODUCT_ITEM_CODE
      ,T.PART_NAME AS PRODUCT_ITEM_NAME
      -- S/N: contract_item_serial (CIS.item_objid = T.contract_item_objid)
      ,(SELECT
          CASE
            WHEN COUNT(*) = 0 THEN ''
            WHEN COUNT(*) = 1 THEN MIN(CIS.serial_no)
            ELSE MIN(CIS.serial_no) || ' 외 ' || (COUNT(*) - 1)::text || '건'
          END
        FROM contract_item_serial CIS
        WHERE CIS.item_objid::varchar = T.CONTRACT_ITEM_OBJID
          AND UPPER(CIS.status) = 'ACTIVE'
          AND CIS.serial_no IS NOT NULL
          AND CIS.serial_no != ''
       ) AS SERIAL_NO
      -- 요청납기: contract_item.due_date → project_mgmt.due_date → contract_mgmt.due_date
      ,COALESCE(
          (SELECT CI.due_date FROM contract_item CI
            WHERE CI.contract_objid = T.CONTRACT_OBJID
              AND CI.part_objid = T.PART_OBJID
              AND CI.status = 'ACTIVE'
            ORDER BY CI.objid DESC LIMIT 1),
          T.DUE_DATE,
          (SELECT CM.due_date FROM contract_mgmt CM WHERE CM.OBJID = T.CONTRACT_OBJID LIMIT 1)
       ) AS REQ_DEL_DATE
      ,T.EBOM_STATUS
      ,T.MBOM_STATUS
      -- 발주일: contract_mgmt.order_date
      ,(SELECT O.order_date FROM contract_mgmt AS O WHERE O.OBJID = T.CONTRACT_OBJID) AS ORDER_DATE
      ,T.RECEIVING_RATE
      ,T.PRODUCTION_TEAM_12
      ,T.PRODUCTION_TEAM_3
      -- 출하일: sales_registration.shipping_date (project_no 매칭)
      ,COALESCE(
          (SELECT TO_CHAR(SR.shipping_date, 'YYYY-MM-DD')
             FROM sales_registration SR
            WHERE SR.project_no = T.PROJECT_NO
            ORDER BY SR.sale_no DESC LIMIT 1),
          ''
       ) AS SHIPMENT_DATE
      ,T.MECHANICAL_TYPE
      ,T.OVERHAUL_ORDER
      ,T.CONTRACT_OBJID

      -- P2: PMS_WBS_TASK 의존 컬럼들은 그리드 표시엔 없으므로 자리만
      ,0 AS TOTAL_RATE
      ,0 AS DESIGN_RATE
      ,0 AS PURCHASE_RATE
      ,0 AS PRODUCE_RATE
      ,0 AS SELFINS_RATE
      ,0 AS FINALINS_RATE
      ,0 AS SHIP_RATE
      ,0 AS SETUP_RATE
      ,0 AS WBS_CNT
      ,NULL::text AS ASSEMBLY
      ,NULL::text AS VERIFICATION
    FROM project_mgmt T
    LEFT JOIN customer_mng C
      ON C.customer_code = CASE WHEN T.CUSTOMER_OBJID LIKE 'C_%' THEN substring(T.CUSTOMER_OBJID, 3) ELSE T.CUSTOMER_OBJID END
    ${where}
    ORDER BY SUBSTRING(T.PROJECT_NO, POSITION('-' IN T.PROJECT_NO)+1) DESC,
             T.OVERHAUL_ORDER DESC NULLS LAST
  `;

  const res = await pool.query(sql, params);
  logger.info("진행관리 목록 조회", { count: res.rowCount, filter });
  return res.rows;
}

// ─── 옵션: 프로젝트번호 셀렉트박스용 ──────────────────────────
// wace `common.getCusProjectNoList` 대응 — 진행관리 메뉴 검색폼 project_no 옵션 채움.

export async function listProjectNoOptions() {
  const pool = getPool();
  const sql = `
    SELECT OBJID AS value, PROJECT_NO AS label
      FROM project_mgmt
     WHERE PROJECT_NO IS NOT NULL AND PROJECT_NO != ''
     ORDER BY SUBSTRING(PROJECT_NO, POSITION('-' IN PROJECT_NO)+1) DESC
  `;
  const res = await pool.query(sql);
  return res.rows;
}

// ─── 단건/수정: P1.5에서 영업관리 OrderRegistDialog 재사용 결정 시 제거 가능 ──

export async function getById(objid: string) {
  const pool = getPool();
  const sql = `
    SELECT
       T.OBJID
      ,T.PROJECT_NO
      ,T.PROJECT_NAME
      ,T.FACILITY
      ,CODE_NAME(T.FACILITY) AS FACILITY_NAME
      ,T.FACILITY_QTY
      ,T.FACILITY_DEPTH
      ,T.CONTRACT_DEL_DATE
      ,T.CONTRACT_CURRENCY
      ,CODE_NAME(T.CONTRACT_CURRENCY) AS CONTRACT_CURRENCY_NAME
      ,T.CONTRACT_PRICE
      ,T.CONTRACT_PRICE_CURRENCY
    FROM project_mgmt T
    WHERE T.OBJID = $1
    LIMIT 1
  `;
  const res = await pool.query(sql, [objid]);
  return res.rows[0] ?? null;
}

export interface ProjectUpdateBody {
  project_no?: string;
  project_name?: string;
  facility?: string;
  facility_qty?: string;
  facility_depth?: string;
  contract_del_date?: string;
  contract_currency?: string;
  contract_price_currency?: string;
  contract_price?: string;
}

export async function updateProject(objid: string, body: ProjectUpdateBody) {
  const pool = getPool();
  const sql = `
    UPDATE project_mgmt
       SET FACILITY_QTY            = $1
          ,PROJECT_NO              = $2
          ,CONTRACT_PRICE          = $3
          ,CONTRACT_PRICE_CURRENCY = $4
          ,CONTRACT_CURRENCY       = $5
          ,PROJECT_NAME            = $6
          ,FACILITY                = $7
          ,FACILITY_DEPTH          = $8
          ,CONTRACT_DEL_DATE       = $9
     WHERE OBJID = $10
  `;
  const params = [
    body.facility_qty ?? "",
    body.project_no ?? "",
    body.contract_price ?? "",
    body.contract_price_currency ?? "",
    body.contract_currency ?? "",
    body.project_name ?? "",
    body.facility ?? "",
    body.facility_depth ?? "",
    body.contract_del_date ?? "",
    objid,
  ];
  const res = await pool.query(sql, params);
  logger.info("진행관리 수정", { objid, rowCount: res.rowCount });
  return res.rowCount ?? 0;
}
