// ============================================================
// 개발관리 PART (M1 등록 / M2 조회) 컨트롤러.
// 라우트:
//   GET    /api/development/part-temp/list     (M1 그리드)
//   POST   /api/development/part-temp/deploy   (M1 → M2 확정)
//   GET    /api/development/part/list          (M2 그리드)
//   GET    /api/development/part/:objid        (단건 상세)
//   POST   /api/development/part               (신규 등록)
//   PUT    /api/development/part/:objid        (상세 수정)
//   DELETE /api/development/part               (다중 삭제, body: { objids })
// ============================================================

import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import * as svc from "../services/devPartService";
import * as excelSvc from "../services/devPartExcelImportService";
import { logger } from "../utils/logger";

function parseListFilter(q: Record<string, any>): svc.PartListFilter {
  const filter: svc.PartListFilter = { ...q };
  if (q.page) filter.page = Number(q.page);
  if (q.page_size) filter.page_size = Number(q.page_size);
  // status_arr 는 ?status_arr=a&status_arr=b 또는 콤마 직렬화 둘 다 수용
  if (q.status_arr) {
    if (Array.isArray(q.status_arr)) filter.status_arr = q.status_arr.map(String);
    else filter.status_arr = String(q.status_arr).split(",").map((s) => s.trim()).filter(Boolean);
  }
  return filter;
}

// ─── M1 그리드 ──────────────────────────────────────────────

export async function getTempList(req: AuthenticatedRequest, res: Response) {
  try {
    const data = await svc.listTemp(parseListFilter(req.query as Record<string, any>));
    return res.json({ success: true, data });
  } catch (e: any) {
    logger.error("개발관리 PART(M1) 목록 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

// ─── M2 그리드 ──────────────────────────────────────────────

export async function getList(req: AuthenticatedRequest, res: Response) {
  try {
    const data = await svc.listRelease(parseListFilter(req.query as Record<string, any>));
    return res.json({ success: true, data });
  } catch (e: any) {
    logger.error("개발관리 PART(M2) 목록 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

// ─── 단건 상세 ──────────────────────────────────────────────

export async function getByObjid(req: AuthenticatedRequest, res: Response) {
  try {
    const { objid } = req.params;
    const row = await svc.getByObjid(objid);
    if (!row) return res.status(404).json({ success: false, message: "not_found" });
    return res.json({ success: true, data: row });
  } catch (e: any) {
    logger.error("개발관리 PART 상세 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

// ─── 신규 등록 ──────────────────────────────────────────────

export async function create(req: AuthenticatedRequest, res: Response) {
  try {
    const userId = req.user!.userId;
    const objid = await svc.create(userId, req.body);
    return res.status(201).json({ success: true, data: { objid }, message: "PART가 등록되었습니다." });
  } catch (e: any) {
    logger.error("개발관리 PART 등록 실패", { error: e.message });
    return res.status(400).json({ success: false, message: e.message });
  }
}

// ─── 상세 수정 ──────────────────────────────────────────────

export async function update(req: AuthenticatedRequest, res: Response) {
  try {
    const { objid } = req.params;
    const rowCount = await svc.update(objid, req.body);
    if (rowCount === 0) return res.status(404).json({ success: false, message: "not_found" });
    return res.json({ success: true, message: "PART가 수정되었습니다." });
  } catch (e: any) {
    logger.error("개발관리 PART 수정 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

// ─── 확정 (M1 → M2) ─────────────────────────────────────────

export async function deploy(req: AuthenticatedRequest, res: Response) {
  try {
    const userId = req.user!.userId;
    const objids = Array.isArray(req.body?.objids) ? (req.body.objids as any[]).map(String) : [];
    if (objids.length === 0) {
      return res.status(400).json({ success: false, message: "objids가 비어있습니다." });
    }
    const result = await svc.deploy(userId, objids);
    return res.json({ success: true, data: result, message: `${result.deployed}건이 확정되었습니다.` });
  } catch (e: any) {
    logger.error("개발관리 PART 확정 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

// ─── Excel Import (M1·M2 공용) ──────────────────────────────
// POST /api/development/part/excel-parse   (multipart, field: file)
// POST /api/development/part/excel-save    (body: { rows: [...] })
//
// 운영판 wace: openPartExcelImportPopUp.jsp → partParsingExcelFile.do + partUploadSave.do
// 본 RPS 구현: 파일을 메모리 파싱 → 검증 결과(NOTE 포함) 반환 / 저장 시 신규 part_no 만 INSERT.

// PART 자동완성 옵션 (IS_LAST='1' 전체) — wace select2-part 1:1
//   GET /api/development/part/options
//   response: { rows: [{ objid, part_no, part_name }] }
export async function partOptions(req: AuthenticatedRequest, res: Response) {
  try {
    const pool = (await import("../database/db")).getPool();
    const r = await pool.query(
      `SELECT OBJID::varchar AS objid, PART_NO AS part_no, PART_NAME AS part_name
         FROM PART_MNG
        WHERE COALESCE(IS_LAST,'') = '1'
          AND PART_NO IS NOT NULL AND PART_NO <> ''
        ORDER BY PART_NO`
    );
    return res.json({ success: true, data: { rows: r.rows } });
  } catch (e: any) {
    logger.error("PART options 조회 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

export async function excelParse(req: AuthenticatedRequest, res: Response) {
  try {
    const file = (req as any).file as Express.Multer.File | undefined;
    if (!file) return res.status(400).json({ success: false, message: "엑셀 파일이 필요합니다." });
    const data = await excelSvc.parseAndValidate(file.buffer);
    return res.json({ success: true, data });
  } catch (e: any) {
    logger.error("PART 엑셀 파싱 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

export async function excelSave(req: AuthenticatedRequest, res: Response) {
  try {
    const userId = req.user!.userId;
    const rows = Array.isArray(req.body?.rows) ? (req.body.rows as excelSvc.SavePartExcelInput[]) : [];
    if (rows.length === 0) {
      return res.status(400).json({ success: false, message: "저장할 행이 없습니다." });
    }
    const result = await excelSvc.saveExcelRows(userId, rows);
    return res.json({
      success: true,
      data: result,
      message: `${result.inserted}건이 저장되었습니다.${result.skipped > 0 ? ` (중복 ${result.skipped}건 건너뜀)` : ""}`,
    });
  } catch (e: any) {
    logger.error("PART 엑셀 저장 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

// ─── 도면 다중 업로드 (wace btnDrawingUpload 1:1) ───────────

export async function drawingMultiUpload(req: AuthenticatedRequest, res: Response) {
  try {
    const userId = (req.user as any)?.userId ?? "system";
    const companyCode = (req.user as any)?.companyCode ?? "COMPANY_16";
    const files = (req.files as Express.Multer.File[]) ?? [];
    if (files.length === 0) {
      return res.status(400).json({ success: false, message: "업로드할 파일이 없습니다." });
    }
    // multipart body — partNoList 는 JSON 문자열로 전달됨.
    //   지정 → 그 목록만 매칭 후보 (M1 현재 그리드 한정)
    //   미지정/빈 배열 → IS_LAST='1' 전체 매칭 (M2 조회 — 페이지 밖도 허용)
    let partNoList: string[] | null = null;
    const raw = req.body?.partNoList;
    if (typeof raw === "string" && raw.trim() !== "") {
      try {
        const parsed = JSON.parse(raw);
        if (Array.isArray(parsed)) partNoList = parsed.map(String).filter(Boolean);
      } catch {
        return res.status(400).json({ success: false, message: "partNoList JSON 파싱 실패" });
      }
    } else if (Array.isArray(raw)) {
      partNoList = raw.map(String).filter(Boolean);
    }
    const result = await svc.drawingMultiUpload(userId, companyCode, files, partNoList);
    return res.json({
      success: true,
      data: result,
      message: `업로드 완료 — 성공 ${result.successCount} / 미매칭 ${result.notFoundCount} / 실패 ${result.failCount}`,
    });
  } catch (e: any) {
    logger.error("도면 다중 업로드 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}

// ─── 다중 삭제 ──────────────────────────────────────────────

export async function removeMany(req: AuthenticatedRequest, res: Response) {
  try {
    const objids = Array.isArray(req.body?.objids) ? (req.body.objids as any[]).map(String) : [];
    if (objids.length === 0) {
      return res.status(400).json({ success: false, message: "objids가 비어있습니다." });
    }
    const removed = await svc.removeMany(objids);
    return res.json({ success: true, data: { removed }, message: `${removed}건이 삭제되었습니다.` });
  } catch (e: any) {
    logger.error("개발관리 PART 삭제 실패", { error: e.message });
    return res.status(500).json({ success: false, message: e.message });
  }
}
