import { Request, Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import {
  getDataflowDiagrams as getDataflowDiagramsService,
  getDataflowDiagramById as getDataflowDiagramByIdService,
  createDataflowDiagram as createDataflowDiagramService,
  updateDataflowDiagram as updateDataflowDiagramService,
  deleteDataflowDiagram as deleteDataflowDiagramService,
  copyDataflowDiagram as copyDataflowDiagramService,
} from "../services/dataflowDiagramService";
import { logger } from "../utils/logger";

/**
 * 관계도 목록 조회 (페이지네이션)
 */
export const getDataflowDiagrams = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const page = parseInt(req.query.page as string) || 1;
    const size = parseInt(req.query.size as string) || 20;
    const searchTerm = req.query.searchTerm as string;
    const userCompanyCode = req.user?.companyCode;

    // 슈퍼 관리자는 쿼리 파라미터로 회사 지정 가능, 일반/회사 관리자는 자신의 회사만
    let companyCode: string;
    if (userCompanyCode === "*") {
      // 슈퍼 관리자: 쿼리 파라미터 사용 또는 전체
      companyCode = (req.query.companyCode as string) || "*";
    } else {
      // 회사 관리자/일반 사용자: 강제로 자신의 회사 코드 적용
      companyCode = userCompanyCode || "*";
    }

    logger.info("관계도 목록 조회", {
      userId: req.user?.userId,
      userCompanyCode,
      filterCompanyCode: companyCode,
      page,
      size,
    });

    const result = await getDataflowDiagramsService(
      companyCode,
      page,
      size,
      searchTerm
    );

    res.json({
      success: true,
      data: result,
    });
  } catch (error) {
    logger.error("관계도 목록 조회 실패:", error);
    res.status(500).json({
      success: false,
      message: "관계도 목록 조회 중 오류가 발생했습니다.",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 특정 관계도 조회
 */
export const getDataflowDiagramById = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const diagramId = parseInt(req.params.diagramId);
    const userCompanyCode = req.user?.companyCode;

    // 슈퍼 관리자는 쿼리 파라미터로 회사 지정 가능, 일반/회사 관리자는 자신의 회사만
    let companyCode: string;
    if (userCompanyCode === "*") {
      companyCode = (req.query.companyCode as string) || "*";
    } else {
      companyCode = userCompanyCode || "*";
    }

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

    const diagram = await getDataflowDiagramByIdService(diagramId, companyCode);

    if (!diagram) {
      return res.status(404).json({
        success: false,
        message: "관계도를 찾을 수 없습니다.",
      });
    }

    return res.json({
      success: true,
      data: diagram,
    });
  } catch (error) {
    logger.error("관계도 조회 실패:", error);
    return res.status(500).json({
      success: false,
      message: "관계도 조회 중 오류가 발생했습니다.",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 새로운 관계도 생성
 */
export const createDataflowDiagram = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const {
      diagram_name,
      relationships,
      node_positions,
      category,
      control,
      plan,
    } = req.body;

    const userCompanyCode = req.user?.companyCode;
    const userId = req.user?.userId || "SYSTEM";

    // 회사 코드는 로그인한 사용자의 회사 코드 사용 (슈퍼 관리자는 요청 body에서 지정 가능)
    let companyCode: string;
    if (userCompanyCode === "*" && req.body.company_code) {
      // 슈퍼 관리자가 특정 회사로 생성하는 경우
      companyCode = req.body.company_code;
    } else {
      // 일반 사용자/회사 관리자는 자신의 회사로 생성
      companyCode = userCompanyCode || "*";
    }

    logger.info(`새 관계도 생성 요청:`, {
      diagram_name,
      companyCode,
      userId,
      userCompanyCode,
    });
    logger.info(`node_positions:`, node_positions);
    logger.info(`category:`, category);
    logger.info(`control:`, control);
    logger.info(`plan:`, plan);

    if (!diagram_name || !relationships) {
      return res.status(400).json({
        success: false,
        message: "관계도 이름과 관계 정보는 필수입니다.",
      });
    }

    const newDiagram = await createDataflowDiagramService({
      diagram_name,
      relationships,
      node_positions,
      category,
      control,
      plan,
      company_code: companyCode,
      created_by: userId,
      updated_by: userId,
    });

    return res.status(201).json({
      success: true,
      data: newDiagram,
      message: "관계도가 성공적으로 생성되었습니다.",
    });
  } catch (error) {
    // 디버깅을 위한 에러 정보 출력
    logger.error("에러 디버깅:", {
      errorType: typeof error,
      errorCode: (error as any)?.code,
      errorMessage: error instanceof Error ? error.message : "Unknown error",
      errorName: (error as any)?.name,
      errorMeta: (error as any)?.meta,
    });

    // 중복 이름 에러인지 먼저 확인 (로그 출력 전에)
    const isDuplicateError =
      (error && typeof error === "object" && (error as any).code === "23505") || // PostgreSQL unique_violation
      (error instanceof Error &&
        (error.message.includes("unique constraint") ||
          error.message.includes("Unique constraint") ||
          error.message.includes("duplicate key") ||
          error.message.includes("UNIQUE constraint failed") ||
          error.message.includes("unique_diagram_name_per_company")));

    if (isDuplicateError) {
      // 중복 에러는 콘솔에 로그 출력하지 않음
      return res.status(409).json({
        success: false,
        message: "중복된 이름입니다.",
      });
    }

    // 다른 에러만 로그 출력
    logger.error("관계도 생성 실패:", error);

    return res.status(500).json({
      success: false,
      message: "관계도 생성 중 오류가 발생했습니다.",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 관계도 수정
 */
export const updateDataflowDiagram = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const diagramId = parseInt(req.params.diagramId);
    const userCompanyCode = req.user?.companyCode;
    const userId = req.user?.userId || "SYSTEM";

    // 슈퍼 관리자는 쿼리 파라미터로 회사 지정 가능, 일반/회사 관리자는 자신의 회사만
    let companyCode: string;
    if (userCompanyCode === "*") {
      companyCode = (req.query.companyCode as string) || "*";
    } else {
      companyCode = userCompanyCode || "*";
    }

    logger.info(`관계도 수정 요청`, {
      diagramId,
      companyCode,
      userId,
      userCompanyCode,
    });
    logger.info(`요청 Body:`, JSON.stringify(req.body, null, 2));
    logger.info(`node_positions:`, req.body.node_positions);

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

    const updateData = {
      ...req.body,
      updated_by: userId,
    };

    const updatedDiagram = await updateDataflowDiagramService(
      diagramId,
      updateData,
      companyCode
    );

    if (!updatedDiagram) {
      return res.status(404).json({
        success: false,
        message: "관계도를 찾을 수 없습니다.",
      });
    }

    return res.json({
      success: true,
      data: updatedDiagram,
      message: "관계도가 성공적으로 수정되었습니다.",
    });
  } catch (error) {
    // 중복 이름 에러인지 먼저 확인 (로그 출력 전에)
    const isDuplicateError =
      (error && typeof error === "object" && (error as any).code === "23505") || // PostgreSQL unique_violation
      (error instanceof Error &&
        (error.message.includes("unique constraint") ||
          error.message.includes("Unique constraint") ||
          error.message.includes("duplicate key") ||
          error.message.includes("UNIQUE constraint failed") ||
          error.message.includes("unique_diagram_name_per_company")));

    if (isDuplicateError) {
      // 중복 에러는 콘솔에 로그 출력하지 않음
      return res.status(409).json({
        success: false,
        message: "중복된 이름입니다.",
      });
    }

    // 다른 에러만 로그 출력
    logger.error("관계도 수정 실패:", error);
    return res.status(500).json({
      success: false,
      message: "관계도 수정 중 오류가 발생했습니다.",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 관계도 삭제
 */
export const deleteDataflowDiagram = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const diagramId = parseInt(req.params.diagramId);
    const userCompanyCode = req.user?.companyCode;

    // 슈퍼 관리자는 쿼리 파라미터로 회사 지정 가능, 일반/회사 관리자는 자신의 회사만
    let companyCode: string;
    if (userCompanyCode === "*") {
      companyCode = (req.query.companyCode as string) || "*";
    } else {
      companyCode = userCompanyCode || "*";
    }

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

    const deleted = await deleteDataflowDiagramService(diagramId, companyCode);

    if (!deleted) {
      return res.status(404).json({
        success: false,
        message: "관계도를 찾을 수 없습니다.",
      });
    }

    return res.json({
      success: true,
      message: "관계도가 성공적으로 삭제되었습니다.",
    });
  } catch (error) {
    logger.error("관계도 삭제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "관계도 삭제 중 오류가 발생했습니다.",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};

/**
 * 관계도 복제
 */
export const copyDataflowDiagram = async (
  req: AuthenticatedRequest,
  res: Response
) => {
  try {
    const diagramId = parseInt(req.params.diagramId);
    const { new_name } = req.body;
    const userCompanyCode = req.user?.companyCode;
    const userId = req.user?.userId || "SYSTEM";

    // 회사 코드는 로그인한 사용자의 회사 코드 사용
    let companyCode: string;
    if (userCompanyCode === "*" && req.body.companyCode) {
      // 슈퍼 관리자가 특정 회사로 복제하는 경우
      companyCode = req.body.companyCode;
    } else {
      // 일반 사용자/회사 관리자는 자신의 회사로 복제
      companyCode = userCompanyCode || "*";
    }

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

    const copiedDiagram = await copyDataflowDiagramService(
      diagramId,
      companyCode,
      new_name,
      userId
    );

    if (!copiedDiagram) {
      return res.status(404).json({
        success: false,
        message: "복제할 관계도를 찾을 수 없습니다.",
      });
    }

    return res.status(201).json({
      success: true,
      data: copiedDiagram,
      message: "관계도가 성공적으로 복제되었습니다.",
    });
  } catch (error) {
    logger.error("관계도 복제 실패:", error);
    return res.status(500).json({
      success: false,
      message: "관계도 복제 중 오류가 발생했습니다.",
      error: error instanceof Error ? error.message : "Unknown error",
    });
  }
};
