import { NextRequest, NextResponse } from "next/server";
import { pool } from "@/lib/db";
import { getSession } from "@/lib/session";

// PART 확정(배포) — 원본 PartMngService.partMngDeploy
// 1) partMngIsLastInit — 같은 part_no의 모든 행 is_last='0'
// 2) partMngDeploy — 대상 행 is_last='1', status='release', revision RE 기본, EO_NO 자동채번
// 3) insertPartMngHistory (HIS_STATUS='DEPLOY') — 이력 저장
// 4) structureQtySave (STATUS='editing') — bom_part_qty 상태 전환
// 5) changeStatusBomReportByPartObjid — 사용된 BOM 설계변경중
// 6) procurStandMgmt.updateCodeName — CODE1~5가 단독 파트에만 쓰이면 procurement_standard.code_name 갱신
export async function POST(request: NextRequest) {
  const user = await getSession();
  if (!user) return NextResponse.json({ success: false }, { status: 401 });

  const body = await request.json();
  // 원본 partMngTempList.jsp: dataListJson = getSelectedData() (full rows)
  // 하위 호환: objIds 만 오면 rows 는 DB에서 조회
  let rows: Array<Record<string, unknown>> = Array.isArray(body.rows) ? body.rows : [];
  if (rows.length === 0 && Array.isArray(body.objIds) && body.objIds.length > 0) {
    const placeholders = body.objIds.map((_: string, i: number) => `$${i + 1}`).join(",");
    const fallback = await pool.query(
      `SELECT objid AS "OBJID", part_no AS "PART_NO", revision AS "REVISION",
              change_type AS "CHANGE_TYPE", change_option AS "CHANGE_OPTION",
              major_category AS "MAJOR_CATEGORY", sub_category AS "SUB_CATEGORY",
              maker AS "MAKER", part_name AS "PART_NAME", spec AS "SPEC",
              code1 AS "CODE1", code2 AS "CODE2", code3 AS "CODE3",
              code4 AS "CODE4", code5 AS "CODE5"
         FROM part_mng WHERE objid IN (${placeholders})`,
      body.objIds,
    );
    rows = fallback.rows;
  }
  if (rows.length === 0) {
    return NextResponse.json({ success: false, message: "선택된 Part가 없습니다." });
  }

  const client = await pool.connect();
  try {
    await client.query("BEGIN");
    for (const r of rows) {
      const objid = String(r.OBJID || "");
      if (!objid) continue;

      // 1) partMngIsLastInit — 같은 part_no의 모든 행 is_last='0'
      await client.query(
        `UPDATE part_mng
            SET is_last = '0', edit_date = NOW()
          WHERE part_no = (SELECT part_no FROM part_mng WHERE objid = $1)`,
        [objid],
      );

      // 2) partMngDeploy — 대상 행 최종 확정
      await client.query(
        `UPDATE part_mng P SET
           is_last = '1',
           edit_date = NOW(),
           deploy_date = NOW(),
           status = 'release',
           revision = CASE WHEN COALESCE(revision, '') = '' THEN 'RE' ELSE revision END,
           eo_date = TO_CHAR(NOW(), 'YYYY-MM-DD'),
           eo_no = CASE
             WHEN P.is_longd = '1' THEN
               'EOB' || TO_CHAR(NOW(),'YY') || '-' || LPAD(
                 COALESCE((SELECT MAX(SUBSTRING(SP.eo_no FROM 7))::integer + 1
                             FROM part_mng SP
                             WHERE SP.eo_no IS NOT NULL
                               AND SP.eo_no LIKE 'EOB' || TO_CHAR(NOW(),'YY') || '-%'
                               AND SP.part_no != P.part_no
                               AND SP.revision != COALESCE(P.revision,''))::text, '1'), 4, '0')
             ELSE
               'EO' || TO_CHAR(NOW(),'YY') || '-' || LPAD(
                 COALESCE((SELECT MAX(SUBSTRING(SP.eo_no FROM 6))::integer + 1
                             FROM part_mng SP
                             WHERE SP.eo_no IS NOT NULL
                               AND SP.eo_no LIKE 'EO' || TO_CHAR(NOW(),'YY') || '-%'
                               AND SP.part_no != P.part_no
                               AND SP.revision != COALESCE(P.revision,''))::text, '1'), 4, '0')
           END
         WHERE P.objid = $1`,
        [objid],
      );

      // 3) insertPartMngHistory (HIS_STATUS='DEPLOY')
      // 원본: REVISION='RE' 면 CHANGE_TYPE을 '0001602'(신규파트생성)로 덮어씀
      const prevRevision = String(r.REVISION || "");
      const changeTypeForHistory = prevRevision === "RE" ? "0001602" : String(r.CHANGE_TYPE || "");
      const childObjId = String(r.CHILD_OBJID || "");
      const bomReportObjId = String(r.BOM_REPORT_OBJID || "");

      await client.query(
        `INSERT INTO part_mng_history (
           objid, product_mgmt_objid, upg_no, part_no, part_name, unit, qty,
           spec, material, weight, part_type, remark, es_spec, ms_spec,
           change_option, design_apply_point, management_flag, revision, status,
           reg_date, edit_date, writer, is_last, eo_no, eo_temp,
           excel_upload_seq, sourcing_code, sub_material, parent_part_no,
           design_date, eo_date, deploy_date,
           thickness, width, height, out_diameter, in_diameter, length, supply_code,
           change_type, contract_objid, maker, qty_temp,
           bom_report_objid, parent_part_objid, parent_qty_child_objid,
           bom_qty_status, his_reg_date, his_writer, his_status, qty_child_objid,
           bom_status, bom_deploy_date, chg_part_objid, chg_part_no, chg_part_rev
         )
         SELECT
           P.objid::numeric, P.product_mgmt_objid, P.upg_no, P.part_no, P.part_name, P.unit, Q.qty,
           P.spec, P.material, P.weight, P.part_type, P.remark, P.es_spec, P.ms_spec,
           COALESCE(NULLIF($1::varchar, ''), P.change_option),
           P.design_apply_point, P.management_flag, P.revision, P.status,
           P.reg_date, NOW(), $2::varchar, P.is_last, P.eo_no, P.eo_temp,
           P.excel_upload_seq, P.sourcing_code, P.sub_material,
           COALESCE(NULLIF(Q.parent_part_no::varchar, ''), Q.parent_part_no),
           P.design_date, P.eo_date, P.deploy_date,
           P.thickness, P.width, P.height, P.out_diameter, P.in_diameter, P.length, P.supply_code,
           COALESCE(NULLIF($3::varchar, ''), P.change_type),
           P.contract_objid, P.maker, Q.qty_temp,
           COALESCE(NULLIF($4::varchar, ''), Q.bom_report_objid),
           Q.parent_part_no, Q.parent_objid,
           Q.status, NOW(), $2::varchar, 'DEPLOY', $5::varchar,
           '', NULL, '', '', ''
         FROM part_mng P
           LEFT OUTER JOIN bom_part_qty Q
             ON Q.child_objid = $5::varchar
              AND Q.status = 'beforeEdit'
         WHERE P.objid = $6::varchar`,
        [
          String(r.CHANGE_OPTION || ""),   // $1
          user.userId,                      // $2
          changeTypeForHistory,             // $3
          bomReportObjId,                   // $4
          childObjId,                       // $5
          objid,                            // $6
        ],
      );

      // 4) structureQtySave — bom_part_qty 상태 'editing'으로 전환
      if (childObjId) {
        await client.query(
          `UPDATE bom_part_qty
              SET status = CASE WHEN COALESCE($1,'') = '' THEN status ELSE $1 END,
                  qty_temp = CASE WHEN COALESCE($2,'') = '' THEN qty_temp ELSE $2 END
            WHERE child_objid = $3`,
          ["editing", "", childObjId],
        );
      }

      // 5) changeStatusBomReportByPartObjid — 이 파트를 사용한 BOM 전체 changeDesign
      await client.query(
        `UPDATE part_bom_report
            SET status = 'changeDesign', edit_date = NOW(), editer = $1
          WHERE objid IN (
            SELECT Q.bom_report_objid
              FROM bom_part_qty Q, part_mng P, part_mng P2
             WHERE P.objid = $2::varchar
               AND P.part_no = P2.part_no
               AND P2.objid = Q.part_no
          )
          AND status != 'changeDesign'`,
        [user.userId, objid],
      );

      // 6) procurStandMgmt.sameStdCodeList + updateCodeName
      // CODE1~5 각각, 해당 코드를 쓰는 is_last='1' 파트가 정확히 1건이면
      // procurement_standard.code_name 갱신 (switch: 1→MAJOR_CATEGORY, 2→SUB_CATEGORY, 3→MAKER, 4→PART_NAME, 5→SPEC)
      const codeMap: Array<[string, string]> = [
        [String(r.CODE1 || ""), String(r.MAJOR_CATEGORY || "")],
        [String(r.CODE2 || ""), String(r.SUB_CATEGORY || "")],
        [String(r.CODE3 || ""), String(r.MAKER || "")],
        [String(r.CODE4 || ""), String(r.PART_NAME || "")],
        [String(r.CODE5 || ""), String(r.SPEC || "")],
      ];
      for (const [codeId, codeName] of codeMap) {
        if (!codeId) continue;
        const cnt = await client.query(
          `SELECT COUNT(*)::int AS cnt FROM part_mng
            WHERE is_last = '1'
              AND ($1 IN (COALESCE(code1,''), COALESCE(code2,''), COALESCE(code3,''), COALESCE(code4,''), COALESCE(code5,'')))`,
          [codeId],
        );
        if (cnt.rows[0]?.cnt === 1) {
          await client.query(
            `UPDATE procurement_standard SET code_name = $1 WHERE code_id = $2`,
            [codeName, codeId],
          );
        }
      }
    }

    await client.query("COMMIT");
    return NextResponse.json({ success: true, message: `${rows.length}건이 확정되었습니다.` });
  } catch (e) {
    await client.query("ROLLBACK");
    console.error("Part deploy:", e);
    return NextResponse.json({ success: false, message: "확정 중 오류가 발생했습니다." }, { status: 500 });
  } finally {
    client.release();
  }
}
