import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import tableCategoryValueService from "../services/tableCategoryValueService";
import { logger } from "../utils/logger";

/**
 * 테이블의 카테고리 컬럼 목록 조회
 */
export const getCategoryColumns = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const { tableName } = req.params;

    const columns = await tableCategoryValueService.getCategoryColumns(
      tableName,
      companyCode
    );

    return res.json({
      success: true,
      data: columns,
    });
  } catch (error: any) {
    logger.error(`카테고리 컬럼 조회 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "카테고리 컬럼 조회 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 모든 테이블의 카테고리 컬럼 목록 조회 (Select 옵션 설정용)
 */
export const getAllCategoryColumns = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;

    const columns = await tableCategoryValueService.getAllCategoryColumns(companyCode);

    return res.json({
      success: true,
      data: columns,
    });
  } catch (error: any) {
    logger.error(`전체 카테고리 컬럼 조회 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "전체 카테고리 컬럼 조회 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 카테고리 값 목록 조회 (메뉴 스코프 적용)
 * 
 * Query Parameters:
 * - menuObjid: 메뉴 OBJID (선택사항, 제공 시 형제 메뉴의 카테고리 값 포함)
 * - includeInactive: 비활성 값 포함 여부
 */
export const getCategoryValues = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const userCompanyCode = req.user!.companyCode;
    const { tableName, columnName } = req.params;
    const includeInactive = req.query.includeInactive === "true";
    const menuObjid = req.query.menuObjid ? Number(req.query.menuObjid) : undefined;
    const filterCompanyCode = req.query.filterCompanyCode as string | undefined;

    // 최고관리자가 특정 회사 기준 필터링을 요청한 경우 해당 회사 코드 사용
    const effectiveCompanyCode = (userCompanyCode === "*" && filterCompanyCode)
      ? filterCompanyCode
      : userCompanyCode;

    logger.info("카테고리 값 조회 요청", {
      tableName,
      columnName,
      menuObjid,
      companyCode: effectiveCompanyCode,
      filterCompanyCode,
    });

    const values = await tableCategoryValueService.getCategoryValues(
      tableName,
      columnName,
      effectiveCompanyCode,
      includeInactive,
      menuObjid
    );

    return res.json({
      success: true,
      data: values,
    });
  } catch (error: any) {
    logger.error(`카테고리 값 조회 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "카테고리 값 조회 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 카테고리 값 추가 (메뉴 스코프)
 * 
 * Body:
 * - menuObjid: 메뉴 OBJID (필수)
 * - 나머지 카테고리 값 정보
 */
export const addCategoryValue = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const { menuObjid, ...value } = req.body;

    if (!menuObjid) {
      return res.status(400).json({
        success: false,
        message: "menuObjid는 필수입니다",
      });
    }

    logger.info("카테고리 값 추가 요청", {
      tableName: value.tableName,
      columnName: value.columnName,
      menuObjid,
      companyCode,
    });

    const newValue = await tableCategoryValueService.addCategoryValue(
      value,
      companyCode,
      userId,
      Number(menuObjid) // ← menuObjid 전달
    );

    return res.status(201).json({
      success: true,
      data: newValue,
    });
  } catch (error: any) {
    logger.error(`카테고리 값 추가 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: error.message || "카테고리 값 추가 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 카테고리 값 수정
 */
export const updateCategoryValue = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const valueId = parseInt(req.params.valueId);
    const updates = req.body;

    if (isNaN(valueId)) {
      return res.status(400).json({
        success: false,
        message: "유효하지 않은 값 ID입니다",
      });
    }

    const updatedValue = await tableCategoryValueService.updateCategoryValue(
      valueId,
      updates,
      companyCode,
      userId
    );

    return res.json({
      success: true,
      data: updatedValue,
    });
  } catch (error: any) {
    logger.error(`카테고리 값 수정 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "카테고리 값 수정 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 카테고리 값 삭제
 */
export const deleteCategoryValue = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const valueId = parseInt(req.params.valueId);

    if (isNaN(valueId)) {
      return res.status(400).json({
        success: false,
        message: "유효하지 않은 값 ID입니다",
      });
    }

    await tableCategoryValueService.deleteCategoryValue(
      valueId,
      companyCode,
      userId
    );

    return res.json({
      success: true,
      message: "카테고리 값이 삭제되었습니다",
    });
  } catch (error: any) {
    logger.error(`카테고리 값 삭제 실패: ${error.message}`);
    
    // 사용 중인 경우 상세 에러 메시지 반환 (400)
    if (error.message.includes("삭제할 수 없습니다")) {
      return res.status(400).json({
        success: false,
        message: error.message,
      });
    }
    
    // 기타 에러 (500)
    return res.status(500).json({
      success: false,
      message: error.message || "카테고리 값 삭제 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 카테고리 값 일괄 삭제
 */
export const bulkDeleteCategoryValues = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const { valueIds } = req.body;

    if (!Array.isArray(valueIds) || valueIds.length === 0) {
      return res.status(400).json({
        success: false,
        message: "삭제할 값 ID 목록이 필요합니다",
      });
    }

    await tableCategoryValueService.bulkDeleteCategoryValues(
      valueIds,
      companyCode,
      userId
    );

    return res.json({
      success: true,
      message: `${valueIds.length}개의 카테고리 값이 삭제되었습니다`,
    });
  } catch (error: any) {
    logger.error(`카테고리 값 일괄 삭제 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "카테고리 값 일괄 삭제 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 카테고리 값 순서 변경
 */
export const reorderCategoryValues = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const { orderedValueIds } = req.body;

    if (!Array.isArray(orderedValueIds) || orderedValueIds.length === 0) {
      return res.status(400).json({
        success: false,
        message: "순서 정보가 필요합니다",
      });
    }

    await tableCategoryValueService.reorderCategoryValues(
      orderedValueIds,
      companyCode
    );

    return res.json({
      success: true,
      message: "카테고리 값 순서가 변경되었습니다",
    });
  } catch (error: any) {
    logger.error(`카테고리 값 순서 변경 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "카테고리 값 순서 변경 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

// ================================================
// 컬럼 매핑 관련 API (논리명 ↔ 물리명)
// ================================================

/**
 * 컬럼 매핑 조회
 * 
 * GET /api/categories/column-mapping/:tableName/:menuObjid
 * 
 * 특정 테이블과 메뉴에 대한 논리적 컬럼명 → 물리적 컬럼명 매핑을 조회합니다.
 * 
 * @returns { logical_column: physical_column } 형태의 매핑 객체
 */
export const getColumnMapping = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const { tableName, menuObjid } = req.params;

    if (!tableName || !menuObjid) {
      return res.status(400).json({
        success: false,
        message: "tableName과 menuObjid는 필수입니다",
      });
    }

    logger.info("컬럼 매핑 조회", {
      tableName,
      menuObjid,
      companyCode,
    });

    const mapping = await tableCategoryValueService.getColumnMapping(
      tableName,
      Number(menuObjid),
      companyCode
    );

    return res.json({
      success: true,
      data: mapping,
    });
  } catch (error: any) {
    logger.error(`컬럼 매핑 조회 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "컬럼 매핑 조회 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 컬럼 매핑 생성/수정
 * 
 * POST /api/categories/column-mapping
 * 
 * Body:
 * - tableName: 테이블명
 * - logicalColumnName: 논리적 컬럼명 (예: status_stock)
 * - physicalColumnName: 물리적 컬럼명 (예: status)
 * - menuObjid: 메뉴 OBJID
 * - description: 설명 (선택사항)
 */
export const createColumnMapping = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const userId = req.user!.userId;
    const {
      tableName,
      logicalColumnName,
      physicalColumnName,
      menuObjid,
      description,
    } = req.body;

    // 입력 검증
    if (!tableName || !logicalColumnName || !physicalColumnName || !menuObjid) {
      return res.status(400).json({
        success: false,
        message: "tableName, logicalColumnName, physicalColumnName, menuObjid는 필수입니다",
      });
    }

    logger.info("컬럼 매핑 생성", {
      tableName,
      logicalColumnName,
      physicalColumnName,
      menuObjid,
      companyCode,
    });

    const mapping = await tableCategoryValueService.createColumnMapping(
      tableName,
      logicalColumnName,
      physicalColumnName,
      Number(menuObjid),
      companyCode,
      userId,
      description
    );

    return res.status(201).json({
      success: true,
      data: mapping,
      message: "컬럼 매핑이 생성되었습니다",
    });
  } catch (error: any) {
    logger.error(`컬럼 매핑 생성 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: error.message || "컬럼 매핑 생성 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 논리적 컬럼 목록 조회
 * 
 * GET /api/categories/logical-columns/:tableName/:menuObjid
 * 
 * 특정 테이블과 메뉴에 대한 논리적 컬럼 목록을 조회합니다.
 * (카테고리 값 추가 시 컬럼 선택용)
 */
export const getLogicalColumns = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const { tableName, menuObjid } = req.params;

    if (!tableName || !menuObjid) {
      return res.status(400).json({
        success: false,
        message: "tableName과 menuObjid는 필수입니다",
      });
    }

    logger.info("논리적 컬럼 목록 조회", {
      tableName,
      menuObjid,
      companyCode,
    });

    const columns = await tableCategoryValueService.getLogicalColumns(
      tableName,
      Number(menuObjid),
      companyCode
    );

    return res.json({
      success: true,
      data: columns,
    });
  } catch (error: any) {
    logger.error(`논리적 컬럼 목록 조회 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "논리적 컬럼 목록 조회 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 컬럼 매핑 삭제
 * 
 * DELETE /api/categories/column-mapping/:mappingId
 */
export const deleteColumnMapping = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const { mappingId } = req.params;

    if (!mappingId) {
      return res.status(400).json({
        success: false,
        message: "mappingId는 필수입니다",
      });
    }

    logger.info("컬럼 매핑 삭제", {
      mappingId,
      companyCode,
    });

    await tableCategoryValueService.deleteColumnMapping(
      Number(mappingId),
      companyCode
    );

    return res.json({
      success: true,
      message: "컬럼 매핑이 삭제되었습니다",
    });
  } catch (error: any) {
    logger.error(`컬럼 매핑 삭제 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: error.message || "컬럼 매핑 삭제 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 테이블+컬럼 기준으로 모든 매핑 삭제
 * 
 * DELETE /api/categories/column-mapping/:tableName/:columnName
 * 
 * 메뉴 선택 변경 시 기존 매핑을 모두 삭제하고 새로운 매핑만 추가하기 위해 사용
 */
export const deleteColumnMappingsByColumn = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const { tableName, columnName } = req.params;

    if (!tableName || !columnName) {
      return res.status(400).json({
        success: false,
        message: "tableName과 columnName은 필수입니다",
      });
    }

    logger.info("테이블+컬럼 기준 매핑 삭제", {
      tableName,
      columnName,
      companyCode,
    });

    const deletedCount = await tableCategoryValueService.deleteColumnMappingsByColumn(
      tableName,
      columnName,
      companyCode
    );

    return res.json({
      success: true,
      message: `${deletedCount}개의 컬럼 매핑이 삭제되었습니다`,
      deletedCount,
    });
  } catch (error: any) {
    logger.error(`테이블+컬럼 기준 매핑 삭제 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: error.message || "컬럼 매핑 삭제 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 카테고리 코드로 라벨 조회
 * 
 * POST /api/table-categories/labels-by-codes
 * 
 * Body:
 * - valueCodes: 카테고리 코드 배열 (예: ["CATEGORY_767659DCUF", "CATEGORY_8292565608"])
 * 
 * Response:
 * - { [code]: label } 형태의 매핑 객체
 */
export const getCategoryLabelsByCodes = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;
    const { valueCodes } = req.body;

    if (!valueCodes || !Array.isArray(valueCodes) || valueCodes.length === 0) {
      return res.json({
        success: true,
        data: {},
      });
    }

    logger.info("카테고리 코드로 라벨 조회", {
      valueCodes,
      companyCode,
    });

    const labels = await tableCategoryValueService.getCategoryLabelsByCodes(
      valueCodes,
      companyCode
    );

    return res.json({
      success: true,
      data: labels,
    });
  } catch (error: any) {
    logger.error(`카테고리 라벨 조회 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "카테고리 라벨 조회 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

/**
 * 2레벨 메뉴 목록 조회
 * 
 * GET /api/categories/second-level-menus
 * 
 * 카테고리 컬럼 매핑 생성 시 메뉴 선택용
 * 2레벨 메뉴를 선택하면 해당 메뉴의 모든 하위 메뉴에서 사용 가능
 */
export const getSecondLevelMenus = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const companyCode = req.user!.companyCode;

    logger.info("2레벨 메뉴 목록 조회", { companyCode });

    const menus = await tableCategoryValueService.getSecondLevelMenus(companyCode);

    return res.json({
      success: true,
      data: menus,
    });
  } catch (error: any) {
    logger.error(`2레벨 메뉴 목록 조회 실패: ${error.message}`);
    return res.status(500).json({
      success: false,
      message: "2레벨 메뉴 목록 조회 중 오류가 발생했습니다",
      error: error.message,
    });
  }
};

