import express from "express";
import { dataService } from "../services/dataService";
import { masterDetailExcelService } from "../services/masterDetailExcelService";
import { multiTableExcelService, TableChainConfig } from "../services/multiTableExcelService";
import { authenticateToken } from "../middleware/authMiddleware";
import { AuthenticatedRequest } from "../types/auth";
import { getPool } from "../database/db";
import { auditLogService } from "../services/auditLogService";
import { TableManagementService } from "../services/tableManagementService";
import { formatPgError } from "../utils/pgErrorUtil";

const router = express.Router();

// ================================
// 마스터-디테일 엑셀 API
// ================================

/**
 * 마스터-디테일 관계 정보 조회
 * GET /api/data/master-detail/relation/:screenId
 */
router.get(
  "/master-detail/relation/:screenId",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { screenId } = req.params;

      if (!screenId || isNaN(parseInt(screenId))) {
        return res.status(400).json({
          success: false,
          message: "유효한 screenId가 필요합니다.",
        });
      }

      console.log(`🔍 마스터-디테일 관계 조회: screenId=${screenId}`);

      const relation = await masterDetailExcelService.getMasterDetailRelation(
        parseInt(screenId),
      );

      if (!relation) {
        return res.json({
          success: true,
          data: null,
          message: "마스터-디테일 구조가 아닙니다.",
        });
      }

      console.log(`✅ 마스터-디테일 관계 발견:`, {
        masterTable: relation.masterTable,
        detailTable: relation.detailTable,
        joinKey: relation.masterKeyColumn,
      });

      return res.json({
        success: true,
        data: relation,
      });
    } catch (error: any) {
      console.error("마스터-디테일 관계 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "마스터-디테일 관계 조회 중 오류가 발생했습니다.",
        error: error.message,
      });
    }
  },
);

/**
 * 마스터-디테일 엑셀 다운로드 데이터 조회
 * POST /api/data/master-detail/download
 */
router.post(
  "/master-detail/download",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { screenId, filters } = req.body;
      const companyCode = req.user?.companyCode || "*";

      if (!screenId) {
        return res.status(400).json({
          success: false,
          message: "screenId가 필요합니다.",
        });
      }

      console.log(`📥 마스터-디테일 엑셀 다운로드: screenId=${screenId}`);

      // 1. 마스터-디테일 관계 조회
      const relation = await masterDetailExcelService.getMasterDetailRelation(
        parseInt(screenId),
      );

      if (!relation) {
        return res.status(400).json({
          success: false,
          message: "마스터-디테일 구조가 아닙니다.",
        });
      }

      // 2. JOIN 데이터 조회
      const data = await masterDetailExcelService.getJoinedData(
        relation,
        companyCode,
        filters,
      );

      console.log(`✅ 마스터-디테일 데이터 조회 완료: ${data.data.length}행`);

      return res.json({
        success: true,
        data,
      });
    } catch (error: any) {
      console.error("마스터-디테일 다운로드 오류:", error);
      return res.status(500).json({
        success: false,
        message: "마스터-디테일 다운로드 중 오류가 발생했습니다.",
        error: error.message,
      });
    }
  },
);

/**
 * 마스터-디테일 엑셀 업로드
 * POST /api/data/master-detail/upload
 */
router.post(
  "/master-detail/upload",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { screenId, data } = req.body;
      const companyCode = req.user?.companyCode || "*";
      const userId = req.user?.userId;

      if (!screenId || !data || !Array.isArray(data)) {
        return res.status(400).json({
          success: false,
          message: "screenId와 data 배열이 필요합니다.",
        });
      }

      console.log(
        `📤 마스터-디테일 엑셀 업로드: screenId=${screenId}, rows=${data.length}`,
      );

      // 1. 마스터-디테일 관계 조회
      const relation = await masterDetailExcelService.getMasterDetailRelation(
        parseInt(screenId),
      );

      if (!relation) {
        return res.status(400).json({
          success: false,
          message: "마스터-디테일 구조가 아닙니다.",
        });
      }

      // 2. 데이터 업로드
      const result = await masterDetailExcelService.uploadJoinedData(
        relation,
        data,
        companyCode,
        userId,
      );

      console.log(`✅ 마스터-디테일 업로드 완료:`, {
        masterInserted: result.masterInserted,
        masterUpdated: result.masterUpdated,
        detailInserted: result.detailInserted,
        detailUpdated: result.detailUpdated,
        errors: result.errors.length,
      });

      const detailTotal = result.detailInserted + (result.detailUpdated || 0);
      const detailMsg = result.detailUpdated
        ? `디테일 신규 ${result.detailInserted}건, 수정 ${result.detailUpdated}건`
        : `디테일 ${result.detailInserted}건`;

      return res.json({
        success: result.success,
        data: result,
        message: result.success
          ? `마스터 ${result.masterInserted + result.masterUpdated}건, ${detailMsg} 처리되었습니다.`
          : "업로드 중 오류가 발생했습니다.",
      });
    } catch (error: any) {
      console.error("마스터-디테일 업로드 오류:", error);
      return res.status(500).json({
        success: false,
        message: "마스터-디테일 업로드 중 오류가 발생했습니다.",
        error: error.message,
      });
    }
  },
);

/**
 * 마스터-디테일 간단 모드 엑셀 업로드
 * - 마스터 정보는 UI에서 선택
 * - 디테일 정보만 엑셀에서 업로드
 * - 채번 규칙을 통해 마스터 키 자동 생성
 *
 * POST /api/data/master-detail/upload-simple
 */
router.post(
  "/master-detail/upload-simple",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const {
        screenId,
        detailData,
        masterFieldValues,
        numberingRuleId,
        afterUploadFlowId,
        afterUploadFlows,
      } = req.body;
      const companyCode = req.user?.companyCode || "*";
      const userId = req.user?.userId || "system";

      if (!screenId || !detailData || !Array.isArray(detailData)) {
        return res.status(400).json({
          success: false,
          message: "screenId와 detailData 배열이 필요합니다.",
        });
      }

      console.log(
        `📤 마스터-디테일 간단 모드 업로드: screenId=${screenId}, rows=${detailData.length}`,
      );
      console.log(`   마스터 필드 값:`, masterFieldValues);
      console.log(`   채번 규칙 ID:`, numberingRuleId);
      console.log(
        `   업로드 후 제어:`,
        afterUploadFlows?.length > 0
          ? `${afterUploadFlows.length}개`
          : afterUploadFlowId || "없음",
      );

      // 업로드 실행
      const result = await masterDetailExcelService.uploadSimple(
        parseInt(screenId),
        detailData,
        masterFieldValues || {},
        numberingRuleId,
        companyCode,
        userId,
        afterUploadFlowId, // 업로드 후 제어 실행 (단일, 하위 호환성)
        afterUploadFlows, // 업로드 후 제어 실행 (다중)
      );

      console.log(`✅ 마스터-디테일 간단 모드 업로드 완료:`, {
        masterInserted: result.masterInserted,
        detailInserted: result.detailInserted,
        generatedKey: result.generatedKey,
        errors: result.errors.length,
      });

      return res.json({
        success: result.success,
        data: result,
        message: result.success
          ? `마스터 1건(${result.generatedKey}), 디테일 ${result.detailInserted}건 처리되었습니다.`
          : "업로드 중 오류가 발생했습니다.",
      });
    } catch (error: any) {
      console.error("마스터-디테일 간단 모드 업로드 오류:", error);
      return res.status(500).json({
        success: false,
        message: "마스터-디테일 업로드 중 오류가 발생했습니다.",
        error: error.message,
      });
    }
  },
);

// ================================
// 다중 테이블 엑셀 업로드 API
// ================================

/**
 * 다중 테이블 자동 감지
 * GET /api/data/multi-table/auto-detect?rootTable=customer_mng
 *
 * 루트 테이블명만 넘기면 FK 관계를 자동 탐색하여
 * 완성된 TableChainConfig를 반환한다.
 */
router.get(
  "/multi-table/auto-detect",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const rootTable = req.query.rootTable as string;
      const screenId = req.query.screenId ? Number(req.query.screenId) : undefined;
      const companyCode = req.user?.companyCode || "*";

      if (!rootTable) {
        return res.status(400).json({
          success: false,
          message: "rootTable 파라미터가 필요합니다.",
        });
      }

      const config = await multiTableExcelService.autoDetectTableChain(
        rootTable,
        companyCode,
        screenId
      );

      return res.json({ success: true, data: config });
    } catch (error: any) {
      console.error("다중 테이블 자동 감지 오류:", error);
      return res.status(500).json({
        success: false,
        message: error.message || "자동 감지 중 오류가 발생했습니다.",
      });
    }
  }
);

/**
 * 다중 테이블 엑셀 업로드
 * POST /api/data/multi-table/upload
 *
 * Body: { config: TableChainConfig, modeId: string, rows: Record<string, any>[] }
 */
router.post(
  "/multi-table/upload",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { config, modeId, rows } = req.body;
      const companyCode = req.user?.companyCode || "*";
      const userId = req.user?.userId || "system";

      if (!config || !modeId || !rows || !Array.isArray(rows)) {
        return res.status(400).json({
          success: false,
          message: "config, modeId, rows 배열이 필요합니다.",
        });
      }

      if (rows.length === 0) {
        return res.status(400).json({
          success: false,
          message: "업로드할 데이터가 없습니다.",
        });
      }

      console.log(`다중 테이블 엑셀 업로드:`, {
        configId: config.id,
        modeId,
        rowCount: rows.length,
        companyCode,
        userId,
      });

      const result = await multiTableExcelService.uploadMultiTable(
        config as TableChainConfig,
        modeId,
        rows,
        companyCode,
        userId
      );

      const summaryParts = result.results.map(
        (r) => `${r.tableName}: 신규 ${r.inserted}건, 수정 ${r.updated}건`
      );

      return res.json({
        success: result.success,
        data: result,
        message: result.success
          ? summaryParts.join(" / ")
          : "업로드 중 오류가 발생했습니다.",
      });
    } catch (error: any) {
      console.error("다중 테이블 업로드 오류:", error);
      return res.status(500).json({
        success: false,
        message: "다중 테이블 업로드 중 오류가 발생했습니다.",
        error: error.message,
      });
    }
  }
);

// ================================
// 기존 데이터 API
// ================================

/**
 * 조인 데이터 조회 API (다른 라우트보다 먼저 정의)
 * GET /api/data/join?leftTable=...&rightTable=...&leftColumn=...&rightColumn=...&leftValue=...
 */
router.get(
  "/join",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const {
        leftTable,
        rightTable,
        leftColumn,
        rightColumn,
        leftValue,
        dataFilter,
        enableEntityJoin,
        displayColumns,
        deduplication,
      } = req.query;

      // 입력값 검증
      if (!leftTable || !rightTable || !leftColumn || !rightColumn) {
        return res.status(400).json({
          success: false,
          message:
            "필수 파라미터가 누락되었습니다 (leftTable, rightTable, leftColumn, rightColumn).",
          error: "MISSING_PARAMETERS",
        });
      }

      // dataFilter 파싱 (JSON 문자열로 전달됨)
      let parsedDataFilter = undefined;
      if (dataFilter && typeof dataFilter === "string") {
        try {
          parsedDataFilter = JSON.parse(dataFilter);
        } catch (error) {
          console.error("dataFilter 파싱 오류:", error);
        }
      }

      // 🆕 enableEntityJoin 파싱
      const enableEntityJoinFlag =
        enableEntityJoin === "true" ||
        (typeof enableEntityJoin === "boolean" && enableEntityJoin);

      // SQL 인젝션 방지를 위한 검증
      const tables = [leftTable as string, rightTable as string];
      const columns = [leftColumn as string, rightColumn as string];

      for (const table of tables) {
        if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(table)) {
          return res.status(400).json({
            success: false,
            message: `유효하지 않은 테이블명입니다: ${table}`,
            error: "INVALID_TABLE_NAME",
          });
        }
      }

      for (const column of columns) {
        if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(column)) {
          return res.status(400).json({
            success: false,
            message: `유효하지 않은 컬럼명입니다: ${column}`,
            error: "INVALID_COLUMN_NAME",
          });
        }
      }

      // 회사 코드 추출 (멀티테넌시 필터링)
      const userCompany = req.user?.companyCode;

      // displayColumns 파싱 (item_info.item_name 등)
      let parsedDisplayColumns:
        | Array<{ name: string; label?: string }>
        | undefined;
      if (displayColumns) {
        try {
          parsedDisplayColumns = JSON.parse(displayColumns as string);
        } catch (e) {
          console.error("displayColumns 파싱 실패:", e);
        }
      }

      // 🆕 deduplication 파싱
      let parsedDeduplication:
        | {
            enabled: boolean;
            groupByColumn: string;
            keepStrategy: "latest" | "earliest" | "base_price" | "current_date";
            sortColumn?: string;
          }
        | undefined;
      if (deduplication) {
        try {
          parsedDeduplication = JSON.parse(deduplication as string);
        } catch (e) {
          console.error("deduplication 파싱 실패:", e);
        }
      }

      console.log(`🔗 조인 데이터 조회:`, {
        leftTable,
        rightTable,
        leftColumn,
        rightColumn,
        leftValue,
        userCompany,
        dataFilter: parsedDataFilter,
        enableEntityJoin: enableEntityJoinFlag,
        displayColumns: parsedDisplayColumns, // 🆕 표시 컬럼 로그
        deduplication: parsedDeduplication, // 🆕 중복 제거 로그
      });

      // 조인 데이터 조회 (회사 코드 + 데이터 필터 + Entity 조인 + 표시 컬럼 + 중복 제거 전달)
      const result = await dataService.getJoinedData(
        leftTable as string,
        rightTable as string,
        leftColumn as string,
        rightColumn as string,
        leftValue as string,
        userCompany,
        parsedDataFilter,
        enableEntityJoinFlag,
        parsedDisplayColumns, // 🆕 표시 컬럼 전달
        parsedDeduplication, // 🆕 중복 제거 설정 전달
      );

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(
        `✅ 조인 데이터 조회 성공: ${result.data?.length || 0}개 항목`,
      );

      return res.json({
        success: true,
        data: result.data,
      });
    } catch (error) {
      console.error("조인 데이터 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "조인 데이터 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

/**
 * 동적 테이블 데이터 조회 API
 * GET /api/data/{tableName}
 */
router.get(
  "/:tableName",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName } = req.params;
      const {
        limit,
        offset,
        page,
        size,
        orderBy,
        searchTerm,
        sortBy,
        sortOrder,
        userLang,
        ...filters
      } = req.query;

      // 입력값 검증
      if (!tableName || typeof tableName !== "string") {
        return res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      // SQL 인젝션 방지를 위한 테이블명 검증
      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      // page/size 또는 limit/offset 방식 지원
      let finalLimit = 100;
      let finalOffset = 0;

      if (page && size) {
        // page/size 방식
        const pageNum = parseInt(page as string) || 1;
        const sizeNum = parseInt(size as string) || 100;
        finalLimit = sizeNum;
        finalOffset = (pageNum - 1) * sizeNum;
      } else if (limit || offset) {
        // limit/offset 방식
        finalLimit = parseInt(limit as string) || 10;
        finalOffset = parseInt(offset as string) || 0;
      }

      console.log(`📊 데이터 조회 요청: ${tableName}`, {
        limit: finalLimit,
        offset: finalOffset,
        orderBy: orderBy || sortBy,
        searchTerm,
        filters,
        user: req.user?.userId,
      });

      // filters에서 searchTerm과 sortOrder 제거 (이미 별도로 처리됨)
      const cleanFilters = { ...filters };
      delete cleanFilters.searchTerm;
      delete cleanFilters.sortOrder;

      // 데이터 조회
      const result = await dataService.getTableData({
        tableName,
        limit: finalLimit,
        offset: finalOffset,
        orderBy: (orderBy || sortBy) as string,
        filters: cleanFilters as Record<string, string>,
        userCompany: req.user?.companyCode,
      });

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(
        `✅ 데이터 조회 성공: ${tableName}, ${result.data?.length || 0}개 항목`,
      );

      // 페이징 정보 포함하여 반환
      const total = result.data?.length || 0;
      const responsePage =
        finalLimit > 0 ? Math.floor(finalOffset / finalLimit) + 1 : 1;
      const responseSize = finalLimit;
      const totalPages = responseSize > 0 ? Math.ceil(total / responseSize) : 1;

      return res.json({
        success: true,
        data: result.data,
        total,
        page: responsePage,
        size: responseSize,
        totalPages,
      });
    } catch (error) {
      console.error("데이터 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "데이터 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

/**
 * 테이블 컬럼 정보 조회 API
 * GET /api/data/{tableName}/columns
 */
router.get(
  "/:tableName/columns",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName } = req.params;

      // 입력값 검증
      if (!tableName || typeof tableName !== "string") {
        return res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      // SQL 인젝션 방지를 위한 테이블명 검증
      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      console.log(`📋 컬럼 정보 조회: ${tableName}`);

      // 컬럼 정보 조회
      const result = await dataService.getTableColumns(tableName);

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(
        `✅ 컬럼 정보 조회 성공: ${tableName}, ${result.data?.length || 0}개 컬럼`,
      );

      return res.json(result);
    } catch (error) {
      console.error("컬럼 정보 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "컬럼 정보 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

/**
 * 레코드 상세 조회 API
 * GET /api/data/{tableName}/{id}
 */
router.get(
  "/:tableName/:id",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName, id } = req.params;

      // 입력값 검증
      if (!tableName || typeof tableName !== "string") {
        return res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      const { enableEntityJoin, groupByColumns, primaryKeyColumn } = req.query;
      const enableEntityJoinFlag =
        enableEntityJoin === "true" ||
        (typeof enableEntityJoin === "boolean" && enableEntityJoin);

      // groupByColumns 파싱 (JSON 문자열 또는 쉼표 구분)
      let groupByColumnsArray: string[] = [];
      if (groupByColumns) {
        try {
          if (typeof groupByColumns === "string") {
            // JSON 형식이면 파싱, 아니면 쉼표로 분리
            groupByColumnsArray = groupByColumns.startsWith("[")
              ? JSON.parse(groupByColumns)
              : groupByColumns.split(",").map((c) => c.trim());
          }
        } catch (error) {
          console.warn("groupByColumns 파싱 실패:", error);
        }
      }

      // 🆕 primaryKeyColumn 파싱
      const primaryKeyColumnStr =
        typeof primaryKeyColumn === "string" ? primaryKeyColumn : undefined;

      console.log(`🔍 레코드 상세 조회: ${tableName}/${id}`, {
        enableEntityJoin: enableEntityJoinFlag,
        groupByColumns: groupByColumnsArray,
        primaryKeyColumn: primaryKeyColumnStr,
      });

      // 레코드 상세 조회 (Entity Join 옵션 + 그룹핑 옵션 + Primary Key 컬럼 포함)
      const result = await dataService.getRecordDetail(
        tableName,
        id,
        enableEntityJoinFlag,
        groupByColumnsArray,
        primaryKeyColumnStr, // 🆕 Primary Key 컬럼명 전달
      );

      if (!result.success) {
        return res.status(400).json(result);
      }

      if (!result.data) {
        return res.status(404).json({
          success: false,
          message: "레코드를 찾을 수 없습니다.",
        });
      }

      console.log(`✅ 레코드 조회 성공: ${tableName}/${id}`);

      return res.json({
        success: true,
        data: result.data,
      });
    } catch (error) {
      console.error("레코드 상세 조회 오류:", error);
      return res.status(500).json({
        success: false,
        message: "레코드 조회 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

/**
 * 그룹화된 데이터 UPSERT API
 * POST /api/data/upsert-grouped
 *
 * 요청 본문:
 * {
 *   tableName: string,
 *   parentKeys: { customer_id: "CUST-0002", item_id: "SLI-2025-0002" },
 *   records: [ { customer_item_code: "84-44", start_date: "2025-11-18", ... }, ... ]
 * }
 */
router.post(
  "/upsert-grouped",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName, parentKeys, records, deleteOrphans = true } = req.body;

      // 입력값 검증
      if (!tableName || !parentKeys || !records || !Array.isArray(records)) {
        return res.status(400).json({
          success: false,
          message:
            "필수 파라미터가 누락되었습니다 (tableName, parentKeys, records).",
          error: "MISSING_PARAMETERS",
        });
      }

      // 테이블명 검증
      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      console.log(`🔄 그룹화된 데이터 UPSERT: ${tableName}`, {
        parentKeys,
        recordCount: records.length,
        userCompany: req.user?.companyCode,
        userId: req.user?.userId,
      });

      // UPSERT 수행
      const result = await dataService.upsertGroupedRecords(
        tableName,
        parentKeys,
        records,
        req.user?.companyCode,
        req.user?.userId,
        deleteOrphans,
      );

      if (!result.success) {
        return res.status(400).json(result);
      }

      const inserted = result.data?.inserted || 0;
      const updated = result.data?.updated || 0;
      const deleted = result.data?.deleted || 0;

      console.log(`✅ 그룹화된 데이터 UPSERT 성공: ${tableName}`, {
        inserted,
        updated,
        deleted,
      });

      const parts: string[] = [];
      if (inserted > 0) parts.push(`${inserted}건 생성`);
      if (updated > 0) parts.push(`${updated}건 수정`);
      if (deleted > 0) parts.push(`${deleted}건 삭제`);

      if (parts.length > 0) {
        auditLogService.log({
          companyCode: req.user?.companyCode || "",
          userId: req.user?.userId || "",
          userName: req.user?.userName || "",
          action:
            inserted > 0 && updated === 0 && deleted === 0
              ? "BATCH_CREATE"
              : "UPDATE",
          resourceType: "DATA",
          tableName,
          summary: `${tableName} 테이블 배치 처리: ${parts.join(", ")}`,
          changes: { after: { inserted, updated, deleted } },
          ipAddress: (req as any).ip,
          requestPath: req.originalUrl,
        });
      }

      return res.json({
        success: true,
        message: "데이터가 저장되었습니다.",
        inserted,
        updated,
        deleted: result.data?.deleted || 0,
        savedIds: result.data?.savedIds || [],
      });
    } catch (error) {
      console.error("그룹화된 데이터 UPSERT 오류:", error);
      return res.status(500).json({
        success: false,
        message: "데이터 저장 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

/**
 * 설비 ID 일괄 검증 API
 * POST /api/data/equipment_mng/validate
 *
 * 요청: { "equipmentIds": ["EQ_001", "EQ_002", "EQ_003"] }
 * 응답: { "success": true, "data": [{ "equipment_id": "EQ_001", "equipment_name": "프레스 1호기" }, ...] }
 *
 * - 존재하는 설비만 반환 (존재하지 않는 ID는 응답에서 제외)
 * - 멀티테넌시: company_code 필터링 적용
 */
router.post(
  "/equipment_mng/validate",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { equipmentIds } = req.body;

      if (!Array.isArray(equipmentIds) || equipmentIds.length === 0) {
        return res.status(400).json({
          success: false,
          message: "equipmentIds 배열이 필요합니다.",
        });
      }

      // 최대 500개 제한
      if (equipmentIds.length > 500) {
        return res.status(400).json({
          success: false,
          message: "한 번에 최대 500개까지 검증할 수 있습니다.",
        });
      }

      const companyCode = req.user?.companyCode;
      const pool = getPool();

      // Parameterized query로 SQL Injection 방지
      const placeholders = equipmentIds.map((_, i) => `$${i + 1}`).join(", ");
      const params: any[] = [...equipmentIds];

      let whereClause = `WHERE equipment_id IN (${placeholders})`;

      // 멀티테넌시 필터링 (company_code가 '*'이 아닌 경우)
      if (companyCode && companyCode !== "*") {
        params.push(companyCode);
        whereClause += ` AND company_code = $${params.length}`;
      }

      const query = `
        SELECT equipment_id, equipment_name
        FROM equipment_mng
        ${whereClause}
      `;

      const result = await pool.query(query, params);

      console.log(
        `✅ 설비 일괄 검증: ${result.rowCount}/${equipmentIds.length}개 확인`,
      );

      return res.json({
        success: true,
        data: result.rows,
      });
    } catch (error: any) {
      console.error("설비 일괄 검증 오류:", error);
      return res.status(500).json({
        success: false,
        message: "설비 검증 중 오류가 발생했습니다.",
        error: error.message,
      });
    }
  },
);

/**
 * 레코드 생성 API
 * POST /api/data/{tableName}
 */
router.post(
  "/:tableName",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName } = req.params;
      const data = req.body;

      // 입력값 검증
      if (!tableName || typeof tableName !== "string") {
        return res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      console.log(`➕ 레코드 생성: ${tableName}`, data);

      // company_code와 company_name 자동 추가 (멀티테넌시)
      const enrichedData = { ...data };

      // 테이블에 company_code 컬럼이 있는지 확인하고 자동으로 추가
      const hasCompanyCode = await dataService.checkColumnExists(
        tableName,
        "company_code",
      );
      if (hasCompanyCode && req.user?.companyCode) {
        enrichedData.company_code = req.user.companyCode;
        console.log(`🏢 company_code 자동 추가: ${req.user.companyCode}`);
      }

      // 테이블에 company_name 컬럼이 있는지 확인하고 자동으로 추가
      const hasCompanyName = await dataService.checkColumnExists(
        tableName,
        "company_name",
      );
      if (hasCompanyName && req.user?.companyName) {
        enrichedData.company_name = req.user.companyName;
        console.log(`🏢 company_name 자동 추가: ${req.user.companyName}`);
      }

      // UNIQUE 제약조건 검증
      const tms = new TableManagementService();
      const uniqueViolations = await tms.validateUniqueConstraints(
        tableName,
        enrichedData,
        req.user?.companyCode || "*"
      );
      if (uniqueViolations.length > 0) {
        return res.status(400).json({
          success: false,
          message: `중복된 값이 존재합니다: ${uniqueViolations.join(", ")}`,
        });
      }

      // 레코드 생성
      const result = await dataService.createRecord(tableName, enrichedData);

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(`✅ 레코드 생성 성공: ${tableName}`);

      auditLogService.log({
        companyCode: req.user?.companyCode || "",
        userId: req.user?.userId || "",
        userName: req.user?.userName || "",
        action: "CREATE",
        resourceType: "DATA",
        resourceId: result.data?.id ? String(result.data.id) : undefined,
        tableName,
        summary: `${tableName} 테이블에 데이터 1건 생성`,
        ipAddress: (req as any).ip,
        requestPath: req.originalUrl,
      });

      return res.status(201).json({
        success: true,
        data: result.data,
        message: "레코드가 생성되었습니다.",
      });
    } catch (error) {
      console.error("레코드 생성 오류:", error);
      return res.status(500).json({
        success: false,
        message: "레코드 생성 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

/**
 * 레코드 수정 API
 * PUT /api/data/{tableName}/{id}
 */
router.put(
  "/:tableName/:id",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName, id } = req.params;
      const data = req.body;

      // 입력값 검증
      if (!tableName || typeof tableName !== "string") {
        return res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      console.log(`✏️ 레코드 수정: ${tableName}/${id}`, data);

      // UNIQUE 제약조건 검증 (자기 자신 제외)
      const tmsUpdate = new TableManagementService();
      const uniqueViolations = await tmsUpdate.validateUniqueConstraints(
        tableName,
        data,
        req.user?.companyCode || "*",
        String(id)
      );
      if (uniqueViolations.length > 0) {
        return res.status(400).json({
          success: false,
          message: `중복된 값이 존재합니다: ${uniqueViolations.join(", ")}`,
        });
      }

      // 레코드 수정
      const result = await dataService.updateRecord(tableName, id, data);

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(`✅ 레코드 수정 성공: ${tableName}/${id}`);

      auditLogService.log({
        companyCode: req.user?.companyCode || "",
        userId: req.user?.userId || "",
        userName: req.user?.userName || "",
        action: "UPDATE",
        resourceType: "DATA",
        resourceId: String(id),
        tableName,
        summary: `${tableName} 테이블 데이터 수정 (ID:${id})`,
        changes: { after: data, fields: Object.keys(data || {}) },
        ipAddress: (req as any).ip,
        requestPath: req.originalUrl,
      });

      return res.json({
        success: true,
        data: result.data,
        message: "레코드가 수정되었습니다.",
      });
    } catch (error) {
      console.error("레코드 수정 오류:", error);
      return res.status(500).json({
        success: false,
        message: "레코드 수정 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

/**
 * 레코드 삭제 API
 * DELETE /api/data/{tableName}/{id}
 */
/**
 * 복합키 레코드 삭제 API (POST)
 * POST /api/data/:tableName/delete
 * Body: { user_id: 'xxx', dept_code: 'yyy' }
 */
router.post(
  "/:tableName/delete",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName } = req.params;
      const compositeKey = req.body;

      // 입력값 검증
      if (!tableName || typeof tableName !== "string") {
        return res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      console.log(`🗑️ 복합키 레코드 삭제: ${tableName}`, compositeKey);

      // 레코드 삭제 (복합키 객체 전달)
      const result = await dataService.deleteRecord(tableName, compositeKey);

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(`✅ 레코드 삭제 성공: ${tableName}`);

      auditLogService.log({
        companyCode: req.user?.companyCode || "",
        userId: req.user?.userId || "",
        userName: req.user?.userName || "",
        action: "DELETE",
        resourceType: "DATA",
        tableName,
        summary: `${tableName} 테이블 데이터 삭제 (복합키)`,
        changes: { before: compositeKey },
        ipAddress: (req as any).ip,
        requestPath: req.originalUrl,
      });

      return res.json(result);
    } catch (error: any) {
      console.error(`레코드 삭제 오류 (${req.params.tableName}):`, error);
      return res.status(500).json({
        success: false,
        message: "레코드 삭제 중 오류가 발생했습니다.",
        error: error.message,
      });
    }
  },
);

/**
 * 그룹 삭제 API
 * POST /api/data/:tableName/delete-group
 */
router.post(
  "/:tableName/delete-group",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName } = req.params;
      const filterConditions = req.body;
      const userCompany = req.user?.companyCode;

      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
        });
      }

      console.log(`🗑️ 그룹 삭제:`, {
        tableName,
        filterConditions,
        userCompany,
      });

      const result = await dataService.deleteGroupRecords(
        tableName,
        filterConditions,
        userCompany, // 회사 코드 전달
      );

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(`✅ 그룹 삭제: ${result.data?.deleted}개`);
      return res.json(result);
    } catch (error: any) {
      console.error("그룹 삭제 오류:", error);
      return res.status(500).json({
        success: false,
        message: "그룹 삭제 실패",
        error: error.message,
      });
    }
  },
);

router.delete(
  "/:tableName/:id",
  authenticateToken,
  async (req: AuthenticatedRequest, res) => {
    try {
      const { tableName, id } = req.params;

      // 입력값 검증
      if (!tableName || typeof tableName !== "string") {
        return res.status(400).json({
          success: false,
          message: "테이블명이 필요합니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)) {
        return res.status(400).json({
          success: false,
          message: "유효하지 않은 테이블명입니다.",
          error: "INVALID_TABLE_NAME",
        });
      }

      console.log(`🗑️ 레코드 삭제: ${tableName}/${id}`);

      // 레코드 삭제
      const result = await dataService.deleteRecord(tableName, id);

      if (!result.success) {
        return res.status(400).json(result);
      }

      console.log(`✅ 레코드 삭제 성공: ${tableName}/${id}`);

      auditLogService.log({
        companyCode: req.user?.companyCode || "",
        userId: req.user?.userId || "",
        userName: req.user?.userName || "",
        action: "DELETE",
        resourceType: "DATA",
        resourceId: String(id),
        tableName,
        summary: `${tableName} 테이블 데이터 삭제 (ID:${id})`,
        ipAddress: (req as any).ip,
        requestPath: req.originalUrl,
      });

      return res.json({
        success: true,
        message: "레코드가 삭제되었습니다.",
      });
    } catch (error) {
      console.error("레코드 삭제 오류:", error);
      return res.status(500).json({
        success: false,
        message: "레코드 삭제 중 오류가 발생했습니다.",
        error: error instanceof Error ? error.message : "Unknown error",
      });
    }
  },
);

export default router;
