import { Response } from "express";
import { screenManagementService } from "../services/screenManagementService";
import { AuthenticatedRequest } from "../types/auth";
import { auditLogService, getClientIp } from "../services/auditLogService";

// 화면 목록 조회
export const getScreens = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const userCompanyCode = (req.user as any).companyCode;
    const { page = 1, size = 20, searchTerm, companyCode, excludePop } = req.query;

    // 쿼리 파라미터로 companyCode가 전달되면 해당 회사의 화면 조회 (최고 관리자 전용)
    // 아니면 현재 사용자의 companyCode 사용
    const targetCompanyCode = (companyCode as string) || userCompanyCode;
    
    // 최고 관리자가 아닌 경우 자신의 회사 코드만 사용 가능
    if (userCompanyCode !== "*" && targetCompanyCode !== userCompanyCode) {
      return res.status(403).json({
        success: false,
        message: "다른 회사의 화면을 조회할 권한이 없습니다.",
      });
    }

    const result = await screenManagementService.getScreensByCompany(
      targetCompanyCode,
      parseInt(page as string),
      parseInt(size as string),
      searchTerm as string,
      { excludePop: excludePop === "true" },
    );

    res.json({
      success: true,
      data: result.data,
      total: result.pagination.total,
      page: result.pagination.page,
      size: result.pagination.size,
      totalPages: result.pagination.totalPages,
    });
  } catch (error) {
    console.error("화면 목록 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 목록 조회에 실패했습니다." });
  }
};

// 단일 화면 조회
export const getScreen = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { id } = req.params;
    const { companyCode } = req.user as any;
    const screen = await screenManagementService.getScreen(
      parseInt(id),
      companyCode
    );

    if (!screen) {
      res.status(404).json({
        success: false,
        message: "화면을 찾을 수 없습니다.",
      });
      return;
    }

    res.json({ success: true, data: screen });
  } catch (error) {
    console.error("화면 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 조회에 실패했습니다." });
  }
};

// 화면에 할당된 메뉴 조회
export const getScreenMenu = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { id } = req.params;
    const { companyCode } = req.user as any;
    
    const menuInfo = await screenManagementService.getMenuByScreen(
      parseInt(id),
      companyCode
    );

    res.json({ success: true, data: menuInfo });
  } catch (error) {
    console.error("화면 메뉴 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 메뉴 조회에 실패했습니다." });
  }
};

// 화면 생성
export const createScreen = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { companyCode } = req.user as any;
    const screenData = { ...req.body, companyCode };
    const newScreen = await screenManagementService.createScreen(
      screenData,
      companyCode
    );

    auditLogService.log({
      companyCode,
      userId: (req.user as any)?.userId || "",
      userName: (req.user as any)?.userName || "",
      action: "CREATE",
      resourceType: "SCREEN",
      resourceId: String(newScreen?.screenId || ""),
      resourceName: newScreen?.screenName || screenData.screenName,
      summary: `화면 "${newScreen?.screenName || screenData.screenName}" 생성`,
      changes: { after: { screenName: newScreen?.screenName, tableName: newScreen?.tableName } },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.status(201).json({ success: true, data: newScreen });
  } catch (error) {
    console.error("화면 생성 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 생성에 실패했습니다." });
  }
};

// 화면 수정
export const updateScreen = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { id } = req.params;
    const { companyCode } = req.user as any;
    const beforeScreen = await screenManagementService.getScreenById(parseInt(id));
    const updateData = { ...req.body, companyCode };
    const updatedScreen = await screenManagementService.updateScreen(
      parseInt(id),
      updateData,
      companyCode
    );

    auditLogService.log({
      companyCode,
      userId: (req.user as any)?.userId || "",
      userName: (req.user as any)?.userName || "",
      action: "UPDATE",
      resourceType: "SCREEN",
      resourceId: id,
      resourceName: updatedScreen?.screenName || updateData.screenName,
      summary: `화면 "${updatedScreen?.screenName || updateData.screenName}" 수정`,
      changes: {
        before: { screenName: beforeScreen?.screenName, tableName: beforeScreen?.tableName, isActive: beforeScreen?.isActive },
        after: { screenName: updateData.screenName, tableName: updateData.tableName, isActive: updateData.isActive },
      },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.json({ success: true, data: updatedScreen });
  } catch (error) {
    console.error("화면 수정 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 수정에 실패했습니다." });
  }
};

// 화면 테이블명 변경
export const updateScreenTableName = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const { tableName } = req.body;

    if (!tableName) {
      return res.status(400).json({ success: false, message: "테이블명이 필요합니다." });
    }

    await screenManagementService.updateScreenTableName(
      parseInt(screenId),
      tableName,
      companyCode
    );

    res.json({ success: true, message: "테이블명이 변경되었습니다." });
  } catch (error) {
    console.error("테이블명 변경 실패:", error);
    res.status(500).json({ success: false, message: "테이블명 변경에 실패했습니다." });
  }
};

// 화면 정보 수정 (메타데이터만)
export const updateScreenInfo = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { id } = req.params;
    const { companyCode } = req.user as any;
    const {
      screenName,
      tableName,
      description,
      isActive,
      // REST API 관련 필드 추가
      dataSourceType,
      dbSourceType,
      dbConnectionId,
      restApiConnectionId,
      restApiEndpoint,
      restApiJsonPath,
    } = req.body;

    console.log("화면 정보 수정 요청:", {
      screenId: id,
      dataSourceType,
      restApiConnectionId,
      restApiEndpoint,
      restApiJsonPath,
    });

    const beforeScreen = await screenManagementService.getScreenById(parseInt(id));

    await screenManagementService.updateScreenInfo(
      parseInt(id),
      {
        screenName,
        tableName,
        description,
        isActive,
        dataSourceType,
        dbSourceType,
        dbConnectionId,
        restApiConnectionId,
        restApiEndpoint,
        restApiJsonPath,
      },
      companyCode
    );

    auditLogService.log({
      companyCode,
      userId: (req.user as any)?.userId || "",
      userName: (req.user as any)?.userName || "",
      action: "UPDATE",
      resourceType: "SCREEN",
      resourceId: id,
      resourceName: screenName,
      summary: `화면 "${screenName}" 정보 수정`,
      changes: {
        before: { screenName: beforeScreen?.screenName, tableName: beforeScreen?.tableName, description: beforeScreen?.description, isActive: beforeScreen?.isActive },
        after: { screenName, tableName, description, isActive },
      },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.json({ success: true, message: "화면 정보가 수정되었습니다." });
  } catch (error) {
    console.error("화면 정보 수정 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 정보 수정에 실패했습니다." });
  }
};

// 화면 의존성 체크
export const checkScreenDependencies = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { id } = req.params;
    const { companyCode } = req.user as any;

    const result = await screenManagementService.checkScreenDependencies(
      parseInt(id),
      companyCode
    );
    res.json({ success: true, ...result });
  } catch (error) {
    console.error("화면 의존성 체크 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "의존성 체크에 실패했습니다." });
  }
};

// 화면 삭제 (휴지통으로 이동)
export const deleteScreen = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { id } = req.params;
    const { companyCode, userId } = req.user as any;
    const { deleteReason, force } = req.body;

    const screenInfo = await screenManagementService.getScreenById(parseInt(id));
    const screenName = screenInfo?.screenName || "";

    await screenManagementService.deleteScreen(
      parseInt(id),
      companyCode,
      userId,
      deleteReason,
      force || false
    );

    auditLogService.log({
      companyCode,
      userId: userId || "",
      userName: (req.user as any)?.userName || "",
      action: "DELETE",
      resourceType: "SCREEN",
      resourceId: id,
      resourceName: screenName,
      summary: `화면(ID:${id}, ${screenName}) 삭제 (사유: ${deleteReason || "없음"})`,
      changes: { before: { deleteReason, force } },
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.json({ success: true, message: "화면이 휴지통으로 이동되었습니다." });
  } catch (error: any) {
    console.error("화면 삭제 실패:", error);

    // 의존성 오류인 경우 특별 처리
    if (error.code === "SCREEN_HAS_DEPENDENCIES") {
      res.status(409).json({
        success: false,
        message: error.message,
        code: error.code,
        dependencies: error.dependencies,
      });
      return;
    }

    res
      .status(500)
      .json({ success: false, message: "화면 삭제에 실패했습니다." });
  }
};

// 화면 복원 (휴지통에서 복원)
export const restoreScreen = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { id } = req.params;
    const { companyCode, userId } = req.user as any;

    await screenManagementService.restoreScreen(
      parseInt(id),
      companyCode,
      userId
    );
    res.json({ success: true, message: "화면이 복원되었습니다." });
  } catch (error) {
    console.error("화면 복원 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 복원에 실패했습니다." });
  }
};

// 화면 영구 삭제
export const permanentDeleteScreen = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { id } = req.params;
    const { companyCode } = req.user as any;

    await screenManagementService.permanentDeleteScreen(
      parseInt(id),
      companyCode
    );
    res.json({ success: true, message: "화면이 영구적으로 삭제되었습니다." });
  } catch (error) {
    console.error("화면 영구 삭제 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 영구 삭제에 실패했습니다." });
  }
};

// 휴지통 화면 목록 조회
export const getDeletedScreens = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { companyCode } = req.user as any;
    const page = parseInt(req.query.page as string) || 1;
    const size = parseInt(req.query.size as string) || 20;

    const result = await screenManagementService.getDeletedScreens(
      companyCode,
      page,
      size
    );
    res.json({ success: true, ...result });
  } catch (error) {
    console.error("휴지통 화면 목록 조회 실패:", error);
    res.status(500).json({
      success: false,
      message: "휴지통 화면 목록 조회에 실패했습니다.",
    });
  }
};

// 활성 화면 일괄 삭제 (휴지통으로 이동)
export const bulkDeleteScreens = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { companyCode, userId } = req.user as any;
    const { screenIds, deleteReason, force } = req.body;

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

    const result = await screenManagementService.bulkDeleteScreens(
      screenIds,
      companyCode,
      userId,
      deleteReason,
      force || false
    );

    let message = `${result.deletedCount}개 화면이 휴지통으로 이동되었습니다.`;
    if (result.skippedCount > 0) {
      message += ` (${result.skippedCount}개 화면은 삭제되지 않았습니다.)`;
    }

    return res.json({
      success: true,
      message,
      result: {
        deletedCount: result.deletedCount,
        skippedCount: result.skippedCount,
        errors: result.errors,
      },
    });
  } catch (error) {
    console.error("활성 화면 일괄 삭제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "일괄 삭제에 실패했습니다.",
    });
  }
};

// 휴지통 화면 일괄 영구 삭제
export const bulkPermanentDeleteScreens = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { companyCode } = req.user as any;
    const { screenIds } = req.body;

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

    const result = await screenManagementService.bulkPermanentDeleteScreens(
      screenIds,
      companyCode
    );

    let message = `${result.deletedCount}개 화면이 영구 삭제되었습니다.`;
    if (result.skippedCount > 0) {
      message += ` (${result.skippedCount}개 화면은 삭제되지 않았습니다.)`;
    }

    return res.json({
      success: true,
      message,
      result: {
        deletedCount: result.deletedCount,
        skippedCount: result.skippedCount,
        errors: result.errors,
      },
    });
  } catch (error) {
    console.error("휴지통 화면 일괄 삭제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "일괄 삭제에 실패했습니다.",
    });
  }
};

// 연결된 모달 화면 감지 (화면 복사 전 확인)
export const detectLinkedScreens = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { id } = req.params;

    const linkedScreens = await screenManagementService.detectLinkedModalScreens(
      parseInt(id)
    );

    res.json({
      success: true,
      data: linkedScreens,
      message: linkedScreens.length > 0
        ? `${linkedScreens.length}개의 연결된 모달 화면을 감지했습니다.`
        : "연결된 모달 화면이 없습니다.",
    });
  } catch (error: any) {
    console.error("연결된 화면 감지 실패:", error);
    res.status(500).json({
      success: false,
      message: error.message || "연결된 화면 감지에 실패했습니다.",
    });
  }
};

// 화면명 중복 체크
export const checkDuplicateScreenName = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { companyCode, screenName } = req.body;

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

    const isDuplicate =
      await screenManagementService.checkDuplicateScreenName(
        companyCode,
        screenName
      );

    res.json({
      success: true,
      data: { isDuplicate },
      message: isDuplicate
        ? "이미 존재하는 화면명입니다."
        : "사용 가능한 화면명입니다.",
    });
  } catch (error: any) {
    console.error("화면명 중복 체크 실패:", error);
    res.status(500).json({
      success: false,
      message: error.message || "화면명 중복 체크에 실패했습니다.",
    });
  }
};

// 화면 일괄 복사 (메인 + 모달 화면들)
export const copyScreenWithModals = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { id } = req.params;
    const { mainScreen, modalScreens, targetCompanyCode } = req.body;
    const { companyCode, userId } = req.user as any;

    if (!mainScreen || !mainScreen.screenName || !mainScreen.screenCode) {
      res.status(400).json({
        success: false,
        message: "메인 화면 정보(screenName, screenCode)가 필요합니다.",
      });
      return;
    }

    const result = await screenManagementService.copyScreenWithModals({
      sourceScreenId: parseInt(id),
      companyCode,
      userId,
      targetCompanyCode, // 최고 관리자가 다른 회사로 복사할 때 사용
      mainScreen: {
        screenName: mainScreen.screenName,
        screenCode: mainScreen.screenCode,
        description: mainScreen.description,
      },
      modalScreens: modalScreens || [],
    });

    res.json({
      success: true,
      data: result,
      message: `화면 복사가 완료되었습니다. (메인 1개 + 모달 ${result.modalScreens.length}개)`,
    });
  } catch (error: any) {
    console.error("화면 일괄 복사 실패:", error);
    res.status(500).json({
      success: false,
      message: error.message || "화면 일괄 복사에 실패했습니다.",
    });
  }
};

// 화면 복사 (단일 - 하위 호환용)
export const copyScreen = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { id } = req.params;
    const { screenName, screenCode, description } = req.body;
    const { companyCode, userId } = req.user as any;

    const copiedScreen = await screenManagementService.copyScreen(
      parseInt(id),
      {
        screenName,
        screenCode,
        description,
        companyCode,
        createdBy: userId,
      }
    );

    res.json({
      success: true,
      data: copiedScreen,
      message: "화면이 복사되었습니다.",
    });
  } catch (error: any) {
    console.error("화면 복사 실패:", error);
    res.status(500).json({
      success: false,
      message: error.message || "화면 복사에 실패했습니다.",
    });
  }
};

// 테이블 목록 조회 (모든 테이블)
export const getTables = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { companyCode } = req.user as any;
    const tables = await screenManagementService.getTables(companyCode);
    res.json({ success: true, data: tables });
  } catch (error) {
    console.error("테이블 목록 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "테이블 목록 조회에 실패했습니다." });
  }
};

// 특정 테이블 정보 조회 (최적화된 단일 테이블 조회)
export const getTableInfo = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { tableName } = req.params;
    const { companyCode } = req.user as any;

    if (!tableName) {
      res.status(400).json({
        success: false,
        message: "테이블명이 필요합니다.",
      });
      return;
    }

    const tableInfo = await screenManagementService.getTableInfo(
      tableName,
      companyCode
    );

    if (!tableInfo) {
      res.status(404).json({
        success: false,
        message: `테이블 '${tableName}'을 찾을 수 없습니다.`,
      });
      return;
    }

    res.json({ success: true, data: tableInfo });
  } catch (error) {
    console.error("테이블 정보 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "테이블 정보 조회에 실패했습니다." });
  }
};

// 테이블 컬럼 정보 조회
export const getTableColumns = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { tableName } = req.params;
    const { companyCode } = req.user as any;
    const columns = await screenManagementService.getTableColumns(
      tableName,
      companyCode
    );
    res.json({ success: true, data: columns });
  } catch (error) {
    console.error("테이블 컬럼 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "테이블 컬럼 조회에 실패했습니다." });
  }
};

// 레이아웃 저장
export const saveLayout = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const layoutData = req.body;
    const savedLayout = await screenManagementService.saveLayout(
      parseInt(screenId),
      layoutData,
      companyCode
    );

    const screenInfo = await screenManagementService.getScreenById(parseInt(screenId));
    auditLogService.log({
      companyCode,
      userId: (req.user as any)?.userId || "",
      userName: (req.user as any)?.userName || "",
      action: "UPDATE",
      resourceType: "SCREEN_LAYOUT",
      resourceId: screenId,
      resourceName: screenInfo?.screenName || "",
      summary: `화면(ID:${screenId}, ${screenInfo?.screenName || ""}) 레이아웃 저장`,
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.json({ success: true, data: savedLayout });
  } catch (error) {
    console.error("레이아웃 저장 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "레이아웃 저장에 실패했습니다." });
  }
};

// 레이아웃 조회
export const getLayout = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const layout = await screenManagementService.getLayout(
      parseInt(screenId),
      companyCode
    );
    res.json({ success: true, data: layout });
  } catch (error) {
    console.error("레이아웃 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "레이아웃 조회에 실패했습니다." });
  }
};

// V1 레이아웃 조회 (component_url + custom_config 기반)
export const getLayoutV1 = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const layout = await screenManagementService.getLayoutV1(
      parseInt(screenId),
      companyCode
    );
    res.json({ success: true, data: layout });
  } catch (error) {
    console.error("V3 레이아웃 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "V3 레이아웃 조회에 실패했습니다." });
  }
};

// V2 레이아웃 조회 (1 레코드 방식 - url + overrides)
export const getLayoutV2 = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode, userType } = req.user as any;
    const layout = await screenManagementService.getLayoutV2(
      parseInt(screenId),
      companyCode,
      userType
    );
    res.json({ success: true, data: layout });
  } catch (error) {
    console.error("V2 레이아웃 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "V2 레이아웃 조회에 실패했습니다." });
  }
};

// V2 레이아웃 저장 (1 레코드 방식 - url + overrides)
export const saveLayoutV2 = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const layoutData = req.body;
    
    await screenManagementService.saveLayoutV2(
      parseInt(screenId),
      layoutData,
      companyCode
    );

    const screenInfo = await screenManagementService.getScreenById(parseInt(screenId));
    auditLogService.log({
      companyCode,
      userId: (req.user as any)?.userId || "",
      userName: (req.user as any)?.userName || "",
      action: "UPDATE",
      resourceType: "SCREEN_LAYOUT",
      resourceId: screenId,
      resourceName: screenInfo?.screenName || "",
      summary: `화면(ID:${screenId}, ${screenInfo?.screenName || ""}) V2 레이아웃 저장`,
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.json({ success: true, message: "V2 레이아웃이 저장되었습니다." });
  } catch (error) {
    console.error("V2 레이아웃 저장 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "V2 레이아웃 저장에 실패했습니다." });
  }
};

// 레이어 목록 조회
export const getScreenLayers = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const layers = await screenManagementService.getScreenLayers(parseInt(screenId), companyCode);
    res.json({ success: true, data: layers });
  } catch (error) {
    console.error("레이어 목록 조회 실패:", error);
    res.status(500).json({ success: false, message: "레이어 목록 조회에 실패했습니다." });
  }
};

// 특정 레이어 레이아웃 조회
export const getLayerLayout = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId, layerId } = req.params;
    const { companyCode } = req.user as any;
    const layout = await screenManagementService.getLayerLayout(parseInt(screenId), parseInt(layerId), companyCode);
    res.json({ success: true, data: layout });
  } catch (error) {
    console.error("레이어 레이아웃 조회 실패:", error);
    res.status(500).json({ success: false, message: "레이어 레이아웃 조회에 실패했습니다." });
  }
};

// 레이어 삭제
export const deleteLayer = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId, layerId } = req.params;
    const { companyCode } = req.user as any;
    await screenManagementService.deleteLayer(parseInt(screenId), parseInt(layerId), companyCode);
    res.json({ success: true, message: "레이어가 삭제되었습니다." });
  } catch (error: any) {
    console.error("레이어 삭제 실패:", error);
    res.status(400).json({ success: false, message: error.message || "레이어 삭제에 실패했습니다." });
  }
};

// 레이어 조건 설정 업데이트
export const updateLayerCondition = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId, layerId } = req.params;
    const { companyCode } = req.user as any;
    const { conditionConfig, layerName } = req.body;
    await screenManagementService.updateLayerCondition(
      parseInt(screenId), parseInt(layerId), companyCode, conditionConfig, layerName
    );
    res.json({ success: true, message: "레이어 조건이 업데이트되었습니다." });
  } catch (error) {
    console.error("레이어 조건 업데이트 실패:", error);
    res.status(500).json({ success: false, message: "레이어 조건 업데이트에 실패했습니다." });
  }
};

// ========================================
// 조건부 영역(Zone) 관리
// ========================================

// Zone 목록 조회
export const getScreenZones = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const zones = await screenManagementService.getScreenZones(parseInt(screenId), companyCode);
    res.json({ success: true, data: zones });
  } catch (error) {
    console.error("Zone 목록 조회 실패:", error);
    res.status(500).json({ success: false, message: "Zone 목록 조회에 실패했습니다." });
  }
};

// Zone 생성
export const createZone = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const zone = await screenManagementService.createZone(parseInt(screenId), companyCode, req.body);
    res.json({ success: true, data: zone });
  } catch (error) {
    console.error("Zone 생성 실패:", error);
    res.status(500).json({ success: false, message: "Zone 생성에 실패했습니다." });
  }
};

// Zone 업데이트 (위치/크기/트리거)
export const updateZone = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { zoneId } = req.params;
    const { companyCode } = req.user as any;
    await screenManagementService.updateZone(parseInt(zoneId), companyCode, req.body);
    res.json({ success: true, message: "Zone이 업데이트되었습니다." });
  } catch (error) {
    console.error("Zone 업데이트 실패:", error);
    res.status(500).json({ success: false, message: "Zone 업데이트에 실패했습니다." });
  }
};

// Zone 삭제
export const deleteZone = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { zoneId } = req.params;
    const { companyCode } = req.user as any;
    await screenManagementService.deleteZone(parseInt(zoneId), companyCode);
    res.json({ success: true, message: "Zone이 삭제되었습니다." });
  } catch (error) {
    console.error("Zone 삭제 실패:", error);
    res.status(500).json({ success: false, message: "Zone 삭제에 실패했습니다." });
  }
};

// Zone에 레이어 추가
export const addLayerToZone = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId, zoneId } = req.params;
    const { companyCode } = req.user as any;
    const { conditionValue, layerName } = req.body;
    const result = await screenManagementService.addLayerToZone(
      parseInt(screenId), companyCode, parseInt(zoneId), conditionValue, layerName
    );
    res.json({ success: true, data: result });
  } catch (error) {
    console.error("Zone 레이어 추가 실패:", error);
    res.status(500).json({ success: false, message: "Zone에 레이어를 추가하지 못했습니다." });
  }
};

// ========================================
// POP 레이아웃 관리 (모바일/태블릿)
// ========================================

// POP 레이아웃 조회
export const getLayoutPop = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode, userType } = req.user as any;
    const layout = await screenManagementService.getLayoutPop(
      parseInt(screenId),
      companyCode,
      userType
    );
    res.json({ success: true, data: layout });
  } catch (error) {
    console.error("POP 레이아웃 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "POP 레이아웃 조회에 실패했습니다." });
  }
};

// POP 레이아웃 저장
export const saveLayoutPop = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode, userId } = req.user as any;
    const layoutData = req.body;
    
    await screenManagementService.saveLayoutPop(
      parseInt(screenId),
      layoutData,
      companyCode,
      userId
    );

    const screenInfo = await screenManagementService.getScreenById(parseInt(screenId));
    auditLogService.log({
      companyCode,
      userId: userId || "",
      userName: (req.user as any)?.userName || "",
      action: "UPDATE",
      resourceType: "SCREEN_LAYOUT",
      resourceId: screenId,
      resourceName: screenInfo?.screenName || "",
      summary: `화면(ID:${screenId}, ${screenInfo?.screenName || ""}) POP 레이아웃 저장`,
      ipAddress: getClientIp(req),
      requestPath: req.originalUrl,
    });

    res.json({ success: true, message: "POP 레이아웃이 저장되었습니다." });
  } catch (error) {
    console.error("POP 레이아웃 저장 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "POP 레이아웃 저장에 실패했습니다." });
  }
};

// POP 레이아웃 삭제
export const deleteLayoutPop = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    
    await screenManagementService.deleteLayoutPop(
      parseInt(screenId),
      companyCode
    );
    res.json({ success: true, message: "POP 레이아웃이 삭제되었습니다." });
  } catch (error) {
    console.error("POP 레이아웃 삭제 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "POP 레이아웃 삭제에 실패했습니다." });
  }
};

// POP 레이아웃 존재하는 화면 ID 목록 조회
export const getScreenIdsWithPopLayout = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { companyCode } = req.user as any;
    
    const screenIds = await screenManagementService.getScreenIdsWithPopLayout(companyCode);
    
    res.json({ 
      success: true, 
      data: screenIds,
      count: screenIds.length
    });
  } catch (error) {
    console.error("POP 레이아웃 화면 ID 목록 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "POP 레이아웃 화면 ID 목록 조회에 실패했습니다." });
  }
};

// 화면 코드 자동 생성
export const generateScreenCode = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { companyCode: paramCompanyCode } = req.params;
    const { companyCode: userCompanyCode } = req.user as any;

    // 사용자의 회사 코드 또는 파라미터의 회사 코드 사용
    const targetCompanyCode = paramCompanyCode || userCompanyCode;

    const generatedCode =
      await screenManagementService.generateScreenCode(targetCompanyCode);
    res.json({ success: true, data: { screenCode: generatedCode } });
  } catch (error) {
    console.error("화면 코드 생성 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면 코드 생성에 실패했습니다." });
  }
};

// 여러 개의 화면 코드 일괄 생성
export const generateMultipleScreenCodes = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { companyCode, count } = req.body;

    if (!companyCode || typeof companyCode !== "string") {
      res.status(400).json({
        success: false,
        message: "회사 코드(companyCode)는 필수입니다.",
      });
      return;
    }

    if (!count || typeof count !== "number" || count < 1 || count > 100) {
      res.status(400).json({
        success: false,
        message: "count는 1~100 사이의 숫자여야 합니다.",
      });
      return;
    }

    const screenCodes =
      await screenManagementService.generateMultipleScreenCodes(
        companyCode,
        count
      );

    res.json({
      success: true,
      data: { screenCodes },
      message: `${count}개의 화면 코드가 생성되었습니다.`,
    });
  } catch (error: any) {
    console.error("화면 코드 일괄 생성 실패:", error);
    res.status(500).json({
      success: false,
      message: error.message || "화면 코드 일괄 생성에 실패했습니다.",
    });
  }
};

// 화면-메뉴 할당
export const assignScreenToMenu = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;
    const assignmentData = { ...req.body, companyCode };

    await screenManagementService.assignScreenToMenu(
      parseInt(screenId),
      assignmentData
    );
    res.json({
      success: true,
      message: "화면이 메뉴에 성공적으로 할당되었습니다.",
    });
  } catch (error) {
    console.error("화면-메뉴 할당 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면-메뉴 할당에 실패했습니다." });
  }
};

// 메뉴별 할당된 화면 목록 조회
export const getScreensByMenu = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { menuObjid } = req.params;
    const { companyCode } = req.user as any;

    const screens = await screenManagementService.getScreensByMenu(
      parseInt(menuObjid),
      companyCode
    );
    res.json({ success: true, data: screens });
  } catch (error) {
    console.error("메뉴별 화면 조회 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "메뉴별 화면 조회에 실패했습니다." });
  }
};

// 화면-메뉴 할당 해제
export const unassignScreenFromMenu = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { screenId, menuObjid } = req.params;
    const { companyCode } = req.user as any;

    await screenManagementService.unassignScreenFromMenu(
      parseInt(screenId),
      parseInt(menuObjid),
      companyCode
    );
    res.json({ success: true, message: "화면-메뉴 할당이 해제되었습니다." });
  } catch (error) {
    console.error("화면-메뉴 할당 해제 실패:", error);
    res
      .status(500)
      .json({ success: false, message: "화면-메뉴 할당 해제에 실패했습니다." });
  }
};

// 휴지통 화면들의 메뉴 할당 정리 (관리자용)
export const cleanupDeletedScreenMenuAssignments = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const result =
      await screenManagementService.cleanupDeletedScreenMenuAssignments();

    return res.json({
      success: true,
      message: result.message,
      updatedCount: result.updatedCount,
    });
  } catch (error) {
    console.error("메뉴 할당 정리 실패:", error);
    return res.status(500).json({
      success: false,
      message: "메뉴 할당 정리에 실패했습니다.",
    });
  }
};

// 그룹 복제 완료 후 탭 컴포넌트의 screenId 참조 일괄 업데이트
export const updateTabScreenReferences = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { targetScreenIds, screenIdMap } = req.body;

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

    if (!screenIdMap || typeof screenIdMap !== "object") {
      return res.status(400).json({
        success: false,
        message: "screenIdMap 객체가 필요합니다.",
      });
    }

    const result = await screenManagementService.updateTabScreenReferences(
      targetScreenIds,
      screenIdMap
    );

    return res.json({
      success: true,
      message: `${result.updated}개 레이아웃의 탭 참조가 업데이트되었습니다.`,
      updated: result.updated,
      details: result.details,
    });
  } catch (error) {
    console.error("탭 screenId 참조 업데이트 실패:", error);
    return res.status(500).json({
      success: false,
      message: "탭 screenId 참조 업데이트에 실패했습니다.",
    });
  }
};

// 화면-메뉴 할당 복제 (다른 회사로 복제 시)
export const copyScreenMenuAssignments = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { sourceCompanyCode, targetCompanyCode, screenIdMap } = req.body;
    const userCompanyCode = req.user?.companyCode;

    // 권한 체크: 최고 관리자만 가능
    if (userCompanyCode !== "*") {
      return res.status(403).json({
        success: false,
        message: "최고 관리자만 이 기능을 사용할 수 있습니다.",
      });
    }

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

    if (!screenIdMap || typeof screenIdMap !== "object") {
      return res.status(400).json({
        success: false,
        message: "screenIdMap 객체가 필요합니다.",
      });
    }

    const result = await screenManagementService.copyScreenMenuAssignments(
      sourceCompanyCode,
      targetCompanyCode,
      screenIdMap
    );

    return res.json({
      success: true,
      message: `화면-메뉴 할당 ${result.copiedCount}개 복제 완료`,
      data: result,
    });
  } catch (error) {
    console.error("화면-메뉴 할당 복제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "화면-메뉴 할당 복제에 실패했습니다.",
    });
  }
};

// 코드 카테고리 + 코드 복제
export const copyCodeCategoryAndCodes = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { sourceCompanyCode, targetCompanyCode } = req.body;
    const userCompanyCode = req.user?.companyCode;

    if (userCompanyCode !== "*") {
      return res.status(403).json({
        success: false,
        message: "최고 관리자만 이 기능을 사용할 수 있습니다.",
      });
    }

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

    const result = await screenManagementService.copyCodeCategoryAndCodes(
      sourceCompanyCode,
      targetCompanyCode
    );

    return res.json({
      success: true,
      message: `코드 카테고리 ${result.copiedCategories}개, 코드 ${result.copiedCodes}개 복제 완료`,
      data: result,
    });
  } catch (error) {
    console.error("코드 카테고리/코드 복제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "코드 카테고리/코드 복제에 실패했습니다.",
    });
  }
};

// 카테고리 매핑 + 값 복제
export const copyCategoryMapping = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { sourceCompanyCode, targetCompanyCode } = req.body;
    const userCompanyCode = req.user?.companyCode;

    if (userCompanyCode !== "*") {
      return res.status(403).json({
        success: false,
        message: "최고 관리자만 이 기능을 사용할 수 있습니다.",
      });
    }

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

    const result = await screenManagementService.copyCategoryMapping(
      sourceCompanyCode,
      targetCompanyCode
    );

    return res.json({
      success: true,
      message: `카테고리 매핑 ${result.copiedMappings}개, 값 ${result.copiedValues}개 복제 완료`,
      data: result,
    });
  } catch (error) {
    console.error("카테고리 매핑/값 복제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "카테고리 매핑/값 복제에 실패했습니다.",
    });
  }
};

// 테이블 타입관리 입력타입 설정 복제
export const copyTableTypeColumns = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { sourceCompanyCode, targetCompanyCode } = req.body;
    const userCompanyCode = req.user?.companyCode;

    if (userCompanyCode !== "*") {
      return res.status(403).json({
        success: false,
        message: "최고 관리자만 이 기능을 사용할 수 있습니다.",
      });
    }

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

    const result = await screenManagementService.copyTableTypeColumns(
      sourceCompanyCode,
      targetCompanyCode
    );

    return res.json({
      success: true,
      message: `테이블 타입 컬럼 ${result.copiedCount}개 복제 완료`,
      data: result,
    });
  } catch (error) {
    console.error("테이블 타입 컬럼 복제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "테이블 타입 컬럼 복제에 실패했습니다.",
    });
  }
};

// 연쇄관계 설정 복제
export const copyCascadingRelation = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const { sourceCompanyCode, targetCompanyCode } = req.body;
    const userCompanyCode = req.user?.companyCode;

    if (userCompanyCode !== "*") {
      return res.status(403).json({
        success: false,
        message: "최고 관리자만 이 기능을 사용할 수 있습니다.",
      });
    }

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

    const result = await screenManagementService.copyCascadingRelation(
      sourceCompanyCode,
      targetCompanyCode
    );

    return res.json({
      success: true,
      message: `연쇄관계 설정 ${result.copiedCount}개 복제 완료`,
      data: result,
    });
  } catch (error) {
    console.error("연쇄관계 설정 복제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "연쇄관계 설정 복제에 실패했습니다.",
    });
  }
};

// POP 화면 연결 분석
export const analyzePopScreenLinks = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { screenId } = req.params;
    const { companyCode } = req.user as any;

    const result = await screenManagementService.analyzePopScreenLinks(
      parseInt(screenId),
      companyCode,
    );

    res.json({ success: true, data: result });
  } catch (error: any) {
    console.error("POP 화면 연결 분석 실패:", error);
    res.status(500).json({
      success: false,
      message: error.message || "POP 화면 연결 분석에 실패했습니다.",
    });
  }
};

// POP 화면 배포 (다른 회사로 복사)
export const deployPopScreens = async (
  req: AuthenticatedRequest,
  res: Response
): Promise<void> => {
  try {
    const { screens, targetCompanyCode, groupStructure } = req.body;
    const { companyCode, userId } = req.user as any;

    if (!screens || !Array.isArray(screens) || screens.length === 0) {
      res.status(400).json({
        success: false,
        message: "배포할 화면 목록이 필요합니다.",
      });
      return;
    }

    if (!targetCompanyCode) {
      res.status(400).json({
        success: false,
        message: "대상 회사 코드가 필요합니다.",
      });
      return;
    }

    if (companyCode !== "*") {
      res.status(403).json({
        success: false,
        message: "최고 관리자만 POP 화면을 배포할 수 있습니다.",
      });
      return;
    }

    const result = await screenManagementService.deployPopScreens({
      screens,
      groupStructure: groupStructure || undefined,
      targetCompanyCode,
      companyCode,
      userId,
    });

    res.json({
      success: true,
      data: result,
      message: `POP 화면 ${result.deployedScreens.length}개가 ${targetCompanyCode}에 배포되었습니다.`,
    });
  } catch (error: any) {
    console.error("POP 화면 배포 실패:", error);
    res.status(500).json({
      success: false,
      message: error.message || "POP 화면 배포에 실패했습니다.",
    });
  }
};
