package com.eactive.eai.rms.onl.dashboard.modern.controller;

import com.eactive.eai.rms.common.context.MonitoringContext;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.common.interceptor.InterceptorSkipController;
import com.eactive.eai.rms.data.entity.onl.property.PropertyService;
import com.eactive.eai.rms.onl.common.service.EaiServerInfoService;
import com.eactive.eai.rms.onl.dashboard.dao.DashboardDAO;
import com.eactive.eai.rms.onl.dashboard.modern.dto.*;
import com.eactive.eai.rms.onl.dashboard.modern.mapper.DashboardDataMapper;
import com.eactive.eai.rms.onl.dashboard.modern.mapper.SmsNotificationMapper;
import com.eactive.eai.rms.onl.dashboard.modern.service.SocketMonitorService;
import com.eactive.eai.rms.onl.dashboard.modern.service.ThroughputCalculationService;
import com.eactive.eai.rms.onl.dashboard.modern.service.TransactionSummaryService;
import com.eactive.eai.rms.onl.dashboard.service.Dashboard2RepositoryService;
import com.eactive.eai.rms.onl.dashboard.service.DashboardService;
import com.eactive.eai.rms.onl.tracking.vo.MemStaticsVo;
import com.eactive.eai.rms.onl.vo.AdaptersVO;
import com.eactive.eai.rms.onl.vo.EAIEngineStatusVo;
import com.eactive.eai.rms.onl.vo.HostStatusVo;
import com.eactive.eai.rms.onl.vo.SmsVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 모던 대시보드 컨트롤러
 * ASIS 대시보드에서 TOBE 대시보드로 마이그레이션된 API를 제공합니다.
 */
@Slf4j
@Controller
public class ModernDashboardController implements InterceptorSkipController {

    @Autowired
    @Qualifier("monitoringContext")
    private transient MonitoringContext monitoringContext;

    @Autowired
    @Qualifier("eaiServerInfoService")
    private EaiServerInfoService eaiServerInfoService;

    @Autowired
    @Qualifier("dashboardService")
    private DashboardService dashboardService;

    @Autowired
    @Qualifier("dashboard2RepositoryService")
    private Dashboard2RepositoryService dashboard2Repository;

    @Autowired
    @Qualifier("dashboardDao")
    private DashboardDAO dashboardDao;

    @Autowired
    private DashboardDataMapper dataMapper;

    @Autowired
    private SmsNotificationMapper smsNotificationMapper;

    @Autowired
    private ThroughputCalculationService throughputCalculationService;

    @Autowired
    private SocketMonitorService socketMonitorService;

    @Autowired
    private TransactionSummaryService transactionSummaryService;

    @Autowired
    @Qualifier("propertyService")
    private PropertyService propertyService;

    /**
     * 모던 대시보드 메인 페이지
     */
    @RequestMapping(path = "/modern-dashboard.do")
    public String modernDashboard(HttpServletRequest request) {
        return "dashboard-modern/modern-dashboard";
    }

    /**
     * 서버 상태 정보 제공 API
     * 전체 서버 및 해당 인스턴스의 상태 정보를 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=server-status")
    @ResponseBody
    public Map<String, Object> getServerStatus(@RequestParam(required = false) String serverName) {
        Map<String, Object> response = new HashMap<>();
        try {
            // 서버 타입 목록 가져오기 (특정 서버 이름이 제공된 경우 해당 서버만 포함)
            List<DataSourceType> serverTypes;
            if (serverName != null && !serverName.isEmpty() && !serverName.equals("all") && !serverName.equals("ALL")) {
                DataSourceType server = DataSourceTypeManager.getDataSourceType(serverName.toUpperCase());
                serverTypes = server != null ? Collections.singletonList(server) : new ArrayList<>();
            } else {
                serverTypes = DataSourceTypeManager.getOnlineDataSourceTypes();

                // GW 추가
                if( DataSourceTypeManager.getDataSourceType("FGW") != null ){
                    serverTypes.add(DataSourceTypeManager.getDataSourceType("FGW"));
                }

                if( DataSourceTypeManager.getDataSourceType("CGW") != null ){
                    serverTypes.add(DataSourceTypeManager.getDataSourceType("CGW"));
                }
            }

            List<ServerStatusDTO> serverList = new ArrayList<>();

            for (DataSourceType serverType : serverTypes) {
                // 서버 컨텍스트 설정
                DataSourceContextHolder.setDataSourceType(serverType);

                // 호스트명으로 인스턴스 그룹화
                Map<String, List<Map<String, String>>> instancesByHost = new HashMap<String, List<Map<String, String>>>();

                // 서버에 대한 인스턴스 목록 조회
                List<Map<String, String>> ipList = eaiServerInfoService.getEaiServerIpListDB();

                for (Map<String, String> instance : ipList) {
                    String hostname = instance.get("HOSTNAME");
                    instancesByHost.computeIfAbsent(hostname, k -> new ArrayList<>()).add(instance);
                }

                // 각 호스트별로 서버 상태 DTO 생성
                for (Map.Entry<String, List<Map<String, String>>> entry : instancesByHost.entrySet()) {
                    String hostname = entry.getKey();
                    List<Map<String, String>> hostInstances = entry.getValue();

                    // 서버 상태 DTO 생성
                    ServerStatusDTO serverDTO = new ServerStatusDTO();
                    serverDTO.setName(hostname);
                    serverDTO.setText(hostname + " (" + serverType.getText() + ")");
                    serverDTO.setHostname(hostname);

                    // 호스트 상태 조회 및 리소스 사용률 설정
                    HostStatusVo hostVo = dashboardService.findHostStatus(hostInstances);
                    if (hostVo != null) {
                        serverDTO.setCpu(hostVo.getCpu());
                        serverDTO.setMemory(hostVo.getMemory());
                        serverDTO.setDisk(hostVo.getDisk());
                    }

                    // 서버 상태 설정
                    if (serverDTO.getCpu() > 90 || serverDTO.getMemory() > 90 || serverDTO.getDisk() > 90) {
                        serverDTO.setStatus("error");
                    } else if (serverDTO.getCpu() > 70 || serverDTO.getMemory() > 70 || serverDTO.getDisk() > 70) {
                        serverDTO.setStatus("warning");
                    } else {
                        serverDTO.setStatus("normal");
                    }

                    // 인스턴스 목록 조회 및 설정
                    List<EAIEngineStatusVo> engineStatusList = dashboardService.findEngineStatus(hostInstances, true);
                    List<InstanceDTO> instances = new ArrayList<>();

                    for (EAIEngineStatusVo engineStatus : engineStatusList) {
                        InstanceDTO instance = new InstanceDTO();
                        instance.setId(engineStatus.getInstanceName());

                        String serverState = StringUtils.defaultString(engineStatus.getServerState());
                        // 인스턴스 상태 설정
                        switch (serverState) {
                            case "0":
                                instance.setStatus("error");
                                break;
                            case "1":
                                instance.setStatus("warning");
                                break;
                            case "2":
                                instance.setStatus("normal");
                                break;
                            default:
                                instance.setStatus("inactive");
                        }

                        // 처리량 설정 (초당 처리량)
                        MemStaticsVo memStatics = dashboard2Repository.getMemTradeVoByHost(
                                engineStatus.getHostName(), engineStatus.getInstanceName());
                        if (memStatics != null) {
                            // 처리량 계산 서비스에서 초당 처리량 가져오기
                            instance.setThroughput(throughputCalculationService.getThroughput(
                                    engineStatus.getHostName(), engineStatus.getInstanceName()));
                        } else {
                            instance.setThroughput("0/s");
                        }

                        instances.add(instance);
                    }

                    serverDTO.setInstances(instances);
                    serverList.add(serverDTO);
                }
            }

            response.put("servers", serverList);
            return response;
        } catch (Exception e) {
            log.error("서버 상태 정보 조회 중 오류 발생", e);
            response.put("error", "서버 상태 정보 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 어댑터 상태 정보 제공 API
     * 서버별 어댑터(Socket, HTTP)의 상태 정보를 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=adapter-status")
    @ResponseBody
    public Map<String, Object> getAdapterStatus(@RequestParam(required = false) String serverName) {
        log.error("[Dashboard Debug] getAdapterStatus API CALLED - serverName: " + serverName);

        Map<String, Object> response = new HashMap<>();
        try {
            // 서버 타입 목록 가져오기 (특정 서버 이름이 제공된 경우 해당 서버만 포함)
            List<DataSourceType> servers;
            if (serverName != null && !serverName.isEmpty() && !serverName.equals("all") && !serverName.equals("ALL")) {
                DataSourceType server = DataSourceTypeManager.getDataSourceType(serverName.toUpperCase());
                servers = server != null ? Collections.singletonList(server) : new ArrayList<>();
            } else {
                // 온라인 데이터 소스 타입 가져오기 (BAT 서버 제외)
                servers = DataSourceTypeManager.getOnlineDataSourceTypes().stream()
                        .filter(server -> !DataSourceTypeManager.BAT.equals(server.getName()))
                        .collect(Collectors.toList());

                // GW 추가
                if( DataSourceTypeManager.getDataSourceType("FGW") != null ){
                    servers.add(DataSourceTypeManager.getDataSourceType("FGW"));
                }

                if( DataSourceTypeManager.getDataSourceType("CGW") != null ){
                    servers.add(DataSourceTypeManager.getDataSourceType("CGW"));
                }
            }

            // TODO: 디버그 완료 후 아래 디버그 로그 전체 삭제 (라인 254-299)
            // [Dashboard Debug] Check server list size
//            System.out.println("[Dashboard Debug] getAdapterStatus: Found " + (servers == null ? 0 : servers.size()) + " servers to check.");
            log.error("[Dashboard Debug] getAdapterStatus: Found " + (servers == null ? 0 : servers.size()) + " servers to check.");

            List<Map<String, Object>> serverAdapters = new ArrayList<>();

            for (DataSourceType server : servers) {
//                System.out.println("[Dashboard Debug] Loop for server: " + server.getName());
                log.error("[Dashboard Debug] Loop for server: " + server.getName());
                // 서버 컨텍스트 설정
                DataSourceContextHolder.setDataSourceType(server);

                // 서버에 대한 인스턴스 목록 조회
//                System.out.println("[Dashboard Debug] Calling getEaiServerIpListDB...");
                List<Map<String, String>> ipList = eaiServerInfoService.getEaiServerIpListDB();
//                System.out.println("[Dashboard Debug] Call to getEaiServerIpListDB finished. IP list size: " + (ipList == null ? 0 : ipList.size()));
                log.error("[Dashboard Debug] Call to getEaiServerIpListDB finished. IP list size: " + (ipList == null ? 0 : ipList.size()));

                // 어댑터 상태 목록 조회 (개별 인스턴스별 상태)
                List<AdaptersVO> adaptersList = dashboardService.findAdapterStatusList(ipList);
//                System.out.println("[Dashboard Debug] adaptersList size: " + (adaptersList == null ? "null" : adaptersList.size()));
                log.error("[Dashboard Debug] adaptersList size: " + (adaptersList == null ? "null" : adaptersList.size()));

                // 어댑터별 상태 코드 로깅
                if (adaptersList != null) {
                    for (int i = 0; i < adaptersList.size(); i++) {
                        AdaptersVO vo = adaptersList.get(i);
                        String debugMsg = "[Dashboard Debug] Adapter[" + i + "] - Host: " + vo.getHostName() +
                                 ", Instance: " + vo.getInstanceName() +
                                 ", Socket(3): " + vo.getSocket(3) +
                                 ", Socket2(3): " + vo.getSocket2(3) +
                                 ", Http(3): " + vo.getHttp(3) +
                                 ", Socket counts: [" + vo.getSocket(0) + "," + vo.getSocket(1) + "," + vo.getSocket(2) + "]" +
                                 ", Socket2 counts: [" + vo.getSocket2(0) + "," + vo.getSocket2(1) + "," + vo.getSocket2(2) + "]" +
                                 ", Http counts: [" + vo.getHttp(0) + "," + vo.getHttp(1) + "," + vo.getHttp(2) + "]";
//                        System.out.println(debugMsg);
                        log.error(debugMsg);
                    }
                }

                // 어댑터 상태 집계 정보 생성
                AdapterStatusSummaryContainerDTO summaryContainer = dataMapper.fromAdaptersVOList(adaptersList);
                String socketSummary = "[Dashboard Debug] Summary - Socket: error=" + summaryContainer.getAdapterSummary("Socket").getErrorCount() +
                         ", warning=" + summaryContainer.getAdapterSummary("Socket").getWarningCount() +
                         ", normal=" + summaryContainer.getAdapterSummary("Socket").getNormalCount() +
                         ", inactive=" + summaryContainer.getAdapterSummary("Socket").getInactiveCount() +
                         ", overall=" + summaryContainer.getAdapterSummary("Socket").getOverallStatus();
                String httpSummary = "[Dashboard Debug] Summary - HTTP: error=" + summaryContainer.getAdapterSummary("HTTP").getErrorCount() +
                         ", warning=" + summaryContainer.getAdapterSummary("HTTP").getWarningCount() +
                         ", normal=" + summaryContainer.getAdapterSummary("HTTP").getNormalCount() +
                         ", inactive=" + summaryContainer.getAdapterSummary("HTTP").getInactiveCount() +
                         ", overall=" + summaryContainer.getAdapterSummary("HTTP").getOverallStatus();
//                System.out.println(socketSummary);
//                System.out.println(httpSummary);
                log.error(socketSummary);
                log.error(httpSummary);
                // TODO: 여기까지 디버그 로그 삭제

                // 기존 방식의 어댑터 상태 정보도 함께 제공 (하위 호환성 유지)
                AdaptersVO adaptersVO = dashboardService.findAdapterStatusTotalList(ipList);
                List<AdapterStatusDTO> adapterDTOs = dataMapper.fromAdaptersVO(adaptersVO);

                Map<String, Object> serverAdapter = new HashMap<>();
                serverAdapter.put("serverName", server.getName());
                serverAdapter.put("serverText", server.getText());
                serverAdapter.put("adapters", adapterDTOs);
                serverAdapter.put("adapterSummaries", summaryContainer.getAdapterSummaryList());
                serverAdapter.put("overallStatus", summaryContainer.getOverallStatus());

                serverAdapters.add(serverAdapter);
            }

            response.put("serverAdapters", serverAdapters);

            return response;
        } catch (Exception e) {
            log.error("어댑터 상태 정보 조회 중 오류 발생", e);
            response.put("error", "어댑터 상태 정보 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 트랜잭션 정보 제공 API
     * 서버별 트랜잭션 처리 현황(성공, 실패, 타임아웃, 시스템 에러)을 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=transaction")
    @ResponseBody
    public Map<String, Object> getTransactionInfo(@RequestParam(required = false) String serverName) {
        Map<String, Object> response = new HashMap<>();
        try {
            // 서버 타입 목록 가져오기 (특정 서버 이름이 제공된 경우 해당 서버만 포함)
            List<DataSourceType> servers;
            if (serverName != null && !serverName.isEmpty() && !serverName.equals("all") && !serverName.equals("ALL")) {
                DataSourceType server = DataSourceTypeManager.getDataSourceType(serverName.toUpperCase());
                servers = server != null ? Collections.singletonList(server) : new ArrayList<>();
            } else {
                servers = DataSourceTypeManager.getOnlineDataSourceTypes();
            }

            List<TransactionDTO> transactions = new ArrayList<>();
            TransactionDTO totalTransaction = new TransactionDTO();
            totalTransaction.setType("TOTAL");

            for (DataSourceType server : servers) {
                // 서버 컨텍스트 설정
                DataSourceContextHolder.setDataSourceType(server);

                // 서버의 트랜잭션 정보 조회
                MemStaticsVo memStatics = dashboard2Repository.getMemTradeVoByService(server.getName());
                TransactionDTO transaction = dataMapper.fromMemStaticsVo(memStatics, server.getName());
                transactions.add(transaction);

                // 전체 트랜잭션 집계에 추가
                totalTransaction.setSuccess(totalTransaction.getSuccess() + transaction.getSuccess());
                totalTransaction.setFail(totalTransaction.getFail() + transaction.getFail());
                totalTransaction.setTimeout(totalTransaction.getTimeout() + transaction.getTimeout());
                totalTransaction.setSyserror(totalTransaction.getSyserror() + transaction.getSyserror());
            }

            // 전체 트랜잭션 정보 추가
            transactions.add(totalTransaction);

            response.put("transactions", transactions);

            return response;
        } catch (Exception e) {
            log.error("트랜잭션 정보 조회 중 오류 발생", e);
            response.put("error", "트랜잭션 정보 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 피크 성능 정보 제공 API
     * 서버별 최대 처리량 및 TPS(초당 트랜잭션 수) 정보를 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=peak-performance")
    @ResponseBody
    public Map<String, Object> getPeakPerformance(@RequestParam(required = false) String type) {
        Map<String, Object> response = new HashMap<>();
        try {
            // 피크 성능 유형 (TPS 또는 거래건수)
            String peakType = type != null && "trade".equals(type) ? "trade" : "tps";

            List<PeakPerformanceDTO> peakTps = new ArrayList<>();
            List<PeakPerformanceDTO> peakTrade = new ArrayList<>();

            // 온라인 서비스 피크 정보 조회
            for (DataSourceType server : DataSourceTypeManager.getOnlineDataSourceTypes()) {
                String peakInfo;
                peakInfo = dashboard2Repository.getPeakTps(server.getName());

                if (peakInfo != null && !peakInfo.isEmpty()) {
                    PeakPerformanceDTO dto = dataMapper.fromPeakPerformanceString(peakInfo, peakType);
                    peakTps.add(dto);
                }

                peakInfo = dashboard2Repository.getPeakTrade(server.getName());

                if (peakInfo != null && !peakInfo.isEmpty()) {
                    PeakPerformanceDTO dto = dataMapper.fromPeakPerformanceString(peakInfo, peakType);
                    peakTrade.add(dto);
                }
            }

            // BAP(일괄전송) 서버 피크 정보 조회
            DataSourceType bapServer = DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.BAP);
            if (bapServer != null) {
                String peakInfo;
//                peakInfo = dashboard2Repository.getPeakTps(bapServer.getName());
//
//                if (peakInfo != null && !peakInfo.isEmpty()) {
//                    PeakPerformanceDTO dto = dataMapper.fromPeakPerformanceString(peakInfo, peakType);
//                    peakTps.add(dto);
//                }

                peakInfo = dashboard2Repository.getPeakTrade(bapServer.getName());

                if (peakInfo != null && !peakInfo.isEmpty()) {
                    PeakPerformanceDTO dto = dataMapper.fromPeakPerformanceString(peakInfo, peakType);
                    peakTrade.add(dto);
                }
            }

            // BAT(배치) 서버 피크 정보 조회
            DataSourceType batServer = DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.BAT);
            if (batServer != null) {
                String peakInfo;
//                peakInfo = dashboard2Repository.getPeakTps(batServer.getName());
//
//                if (peakInfo != null && !peakInfo.isEmpty()) {
//                    PeakPerformanceDTO dto = dataMapper.fromPeakPerformanceString(peakInfo, peakType);
//                    peakTps.add(dto);
//                }

                peakInfo = dashboard2Repository.getPeakTrade(batServer.getName());

                if (peakInfo != null && !peakInfo.isEmpty()) {
                    PeakPerformanceDTO dto = dataMapper.fromPeakPerformanceString(peakInfo, peakType);
                    peakTrade.add(dto);
                }
            }

            response.put("peakTps", peakTps);
            response.put("peakTrade", peakTrade);
            response.put("peakType", peakType);

            return response;
        } catch (Exception e) {
            log.error("피크 성능 정보 조회 중 오류 발생", e);
            response.put("error", "피크 성능 정보 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 배치 처리 상태 제공 API
     * 일괄 전송(BAP) 및 배치(BAT) 처리 상태 정보를 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=batch-process")
    @ResponseBody
    public Map<String, Object> getBatchProcess() {
        Map<String, Object> response = new HashMap<>();
        try {
            List<BatchProcessDTO> batchData = new ArrayList<>();

            // BAP(일괄전송) 배치 처리 정보 조회
            if( DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.BAP) != null ){
                String bapBatchInfo = dashboard2Repository.getProcBatch();
                if (bapBatchInfo != null && !bapBatchInfo.isEmpty()) {
                    BatchProcessDTO bapDTO = dataMapper.fromBatchProcessString(DataSourceTypeManager.BAP, bapBatchInfo);
                    batchData.add(bapDTO);
                }
            }

            // BAT(배치) 배치 처리 정보 조회
            if( DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.BAT) != null ){
                String batBatchInfo = dashboard2Repository.getProcEaiBatch();
                if (batBatchInfo != null && !batBatchInfo.isEmpty()) {
                    BatchProcessDTO batDTO = dataMapper.fromBatchProcessString(DataSourceTypeManager.BAT, batBatchInfo);
                    batchData.add(batDTO);
                }
            }

            response.put("batchData", batchData);

            return response;
        } catch (Exception e) {
            log.error("배치 처리 정보 조회 중 오류 발생", e);
            response.put("error", "배치 처리 정보 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 인스턴스 상세 정보 제공 API
     * 특정 서버 또는 모든 서버의 인스턴스별 상세 정보를 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=instance-detail")
    @ResponseBody
    public Map<String, Object> getInstanceDetail(@RequestParam(required = false) String serverName) {
        Map<String, Object> response = new HashMap<>();
        try {
            // 서버 타입 목록 가져오기 (특정 서버 이름이 제공된 경우 해당 서버만 포함)
            List<DataSourceType> servers;
            if (serverName != null && !serverName.isEmpty() && !serverName.equals("all") && !serverName.equals("ALL")) {
                DataSourceType server = DataSourceTypeManager.getDataSourceType(serverName.toUpperCase());
                servers = server != null ? Collections.singletonList(server) : new ArrayList<>();
            } else {
                servers = DataSourceTypeManager.getOnlineDataSourceTypes();
            }

            List<Map<String, Object>> instanceDetails = new ArrayList<>();

            for (DataSourceType server : servers) {
                // 서버 컨텍스트 설정
                DataSourceContextHolder.setDataSourceType(server);

                // 서버에 대한 인스턴스 목록 조회
                List<Map<String, String>> ipList = eaiServerInfoService.getEaiServerIpListDB();

                // 각 인스턴스별 상세 정보 수집
                for (Map<String, String> instanceInfo : ipList) {
                    String hostName = instanceInfo.get("HOSTNAME");
                    String instanceName = instanceInfo.get("EAISVRINSTNM");

                    // 엔진 상태 조회
                    EAIEngineStatusVo engineStatus = new EAIEngineStatusVo();
                    engineStatus.setHostName(hostName);
                    engineStatus.setInstanceName(instanceName);
                    engineStatus.setService(server.getName());

                    EAIEngineStatusVo engineStatusResult = dashboardService.findEngineStatus(engineStatus);

                    // 어댑터 상태 조회
                    AdaptersVO adaptersVO = new AdaptersVO();
                    adaptersVO.setHostName(hostName);
                    adaptersVO.setInstanceName(instanceName);
                    adaptersVO.setService(server.getName());

                    AdaptersVO adaptersResult = dashboardService.findAdapterStatus(adaptersVO);

                    // 트랜잭션 정보 조회
                    MemStaticsVo memStatics = dashboard2Repository.getMemTradeVoByHost(hostName, instanceName);

                    // DTO로 변환
                    ServerStatusDTO serverDTO = dataMapper.fromEAIEngineStatusVo(engineStatusResult);
                    List<AdapterStatusDTO> adapterDTOs = dataMapper.fromAdaptersVO(adaptersResult);
                    TransactionDTO transactionDTO = dataMapper.fromMemStaticsVo(memStatics, server.getName());

                    // 인스턴스 상세 정보 구성
                    Map<String, Object> instanceDetail = new HashMap<>();
                    instanceDetail.put("serverName", server.getName());
                    instanceDetail.put("serverText", server.getText());
                    instanceDetail.put("hostName", hostName);
                    instanceDetail.put("instanceName", instanceName);
                    instanceDetail.put("server", serverDTO);
                    instanceDetail.put("adapters", adapterDTOs);
                    instanceDetail.put("transaction", transactionDTO);

                    instanceDetails.add(instanceDetail);
                }
            }

            response.put("instanceDetails", instanceDetails);

            return response;
        } catch (Exception e) {
            log.error("인스턴스 상세 정보 조회 중 오류 발생", e);
            response.put("error", "인스턴스 상세 정보 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 실시간 성능 데이터 제공 API
     * 서버 및 어댑터의 최신 성능 데이터를 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=performance-data")
    @ResponseBody
    public Map<String, Object> getPerformanceData() {
        Map<String, Object> response = new HashMap<>();
        try {
            // 서버별 성능 정보 수집
            List<Map<String, Object>> serverPerformance = new ArrayList<>();

            for (DataSourceType server : DataSourceTypeManager.getOnlineDataSourceTypes()) {
                // 서버 컨텍스트 설정
                DataSourceContextHolder.setDataSourceType(server);

                // 서버에 대한 인스턴스 목록 조회
                List<Map<String, String>> ipList = eaiServerInfoService.getEaiServerIpListDB();

                // 호스트 상태 조회
                HostStatusVo hostVo = dashboardService.findHostStatus(ipList);

                // 실시간 트랜잭션 정보 조회
                MemStaticsVo memStatics = dashboard2Repository.getMemTradeVoByService(server.getName());

                // 서버 성능 정보 구성
                Map<String, Object> performance = new HashMap<>();
                performance.put("serverName", server.getName());
                performance.put("serverText", server.getText());
                performance.put("cpu", hostVo != null ? hostVo.getCpu() : 0);
                performance.put("memory", hostVo != null ? hostVo.getMemory() : 0);
                performance.put("disk", hostVo != null ? hostVo.getDisk() : 0);
                performance.put("procTotal", memStatics != null ? memStatics.getProcTotal() : 0);
                performance.put("errorTotal", memStatics != null ?
                        (memStatics.getErrorTotal() + memStatics.getTimeoutTotal() + memStatics.getSysErrorTotal()) : 0);

                serverPerformance.add(performance);
            }

            response.put("serverPerformance", serverPerformance);
            response.put("timestamp", System.currentTimeMillis());

            return response;
        } catch (Exception e) {
            log.error("성능 데이터 조회 중 오류 발생", e);
            response.put("error", "성능 데이터 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 트랜잭션 시계열 데이터 제공 API
     * 서버별 시간에 따른 트랜잭션 처리 현황(성공, 실패, 타임아웃, 시스템 에러)을 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=transaction-timeseries")
    @ResponseBody
    public Map<String, Object> getTransactionTimeSeries(
            @RequestParam(required = false) String serverName,
            @RequestParam(required = false, defaultValue = "10") int minutes) {

        Map<String, Object> response = new HashMap<>();
        try {
            // 서버 타입 목록 가져오기 (특정 서버 이름이 제공된 경우 해당 서버만 포함)
            List<DataSourceType> servers;
            if (serverName != null && !serverName.isEmpty() && !serverName.equals("all") && !serverName.equals("ALL")) {
                DataSourceType server = DataSourceTypeManager.getDataSourceType(serverName.toUpperCase());
                servers = server != null ? Collections.singletonList(server) : new ArrayList<>();
            } else {
                servers = DataSourceTypeManager.getOnlineDataSourceTypes();
            }

            // 시계열 데이터 수집 기간 제한 (기본 10분)
            minutes = Math.min(Math.max(minutes, 1), 60); // 1~60분 범위로 제한

            // 서버별 시계열 데이터 수집
            Map<String, Map<String, Object>> timeSeriesData = new HashMap<>();

            // 현재 시간 저장
            long currentTimestamp = System.currentTimeMillis();

            // 현재 실시간 거래 정보 저장용 맵
            Map<String, MemStaticsVo> currentTransactions = new HashMap<>();

            // 현재 거래 정보 먼저 조회 (실시간 값 추가용)
            for (DataSourceType server : servers) {
                String serverType = server.getName();

                // 서버 컨텍스트 설정
                DataSourceContextHolder.setDataSourceType(server);

                // 서버의 트랜잭션 정보 조회
                MemStaticsVo memStatics = dashboard2Repository.getMemTradeVoByService(serverType);
                if (memStatics != null) {
                    currentTransactions.put(serverType, memStatics);
                }
            }

            // ThroughputCalculationService에서 시계열 데이터 가져오기
            for (DataSourceType server : servers) {
                String serverType = server.getName();

                // 시계열 데이터 조회
                ThroughputCalculationService.TimeSeriesData seriesData =
                        throughputCalculationService.getTimeSeriesData(serverType, minutes);

                if (seriesData != null) {
                    // 시계열 데이터 저장할 구조 생성
                    Map<String, Object> serviceData = new HashMap<>();

                    // 기존 타임스탬프와 데이터 복사
                    List<Long> timestamps = new ArrayList<>(seriesData.getTimestamps());
                    List<Integer> success = new ArrayList<>(seriesData.getSuccess());
                    List<Integer> fail = new ArrayList<>(seriesData.getFail());
                    List<Integer> timeout = new ArrayList<>(seriesData.getTimeout());
                    List<Integer> syserror = new ArrayList<>(seriesData.getSyserror());

                    // 현재 값을 시계열에 추가 (마지막 데이터가 없거나 10초 이상 지났을 경우)
                    MemStaticsVo currentStats = currentTransactions.get(serverType);
                    if (currentStats != null) {
                        boolean shouldAddCurrentData = true;

                        // 마지막 데이터와 현재 시간이 2초 이상 차이가 나면 현재 값 추가
                        if (!timestamps.isEmpty() && (currentTimestamp - timestamps.get(timestamps.size() - 1)) < 2000) {
                            shouldAddCurrentData = false;
                        }

                        if (shouldAddCurrentData) {
                            // 현재 값을 시계열 마지막에 추가
                            timestamps.add(currentTimestamp);

                            // 성공 건수 = 전체 - (실패 + 타임아웃 + 시스템에러)
                            int successCount = currentStats.getProcTotal() - currentStats.getErrorTotal()
                                    - currentStats.getTimeoutTotal() - currentStats.getSysErrorTotal();

                            success.add(Math.max(0, successCount));
                            fail.add(currentStats.getErrorTotal());
                            timeout.add(currentStats.getTimeoutTotal());
                            syserror.add(currentStats.getSysErrorTotal());
                        }
                    }

                    // 최종 데이터 저장
                    serviceData.put("timestamps", timestamps);
                    serviceData.put("success", success);
                    serviceData.put("fail", fail);
                    serviceData.put("timeout", timeout);
                    serviceData.put("syserror", syserror);

                    // 이 서버의 데이터 저장
                    timeSeriesData.put(serverType, serviceData);
                } else {
                    // 데이터가 없는 경우 빈 데이터 생성
                    Map<String, Object> emptyData = new HashMap<>();
                    emptyData.put("timestamps", new ArrayList<>());
                    emptyData.put("success", new ArrayList<>());
                    emptyData.put("fail", new ArrayList<>());
                    emptyData.put("timeout", new ArrayList<>());
                    emptyData.put("syserror", new ArrayList<>());
                    timeSeriesData.put(serverType, emptyData);
                }
            }

            // 전체 합계 데이터 조회
            ThroughputCalculationService.TimeSeriesData totalData =
                    throughputCalculationService.getTimeSeriesData("TOTAL", minutes);

            if (totalData != null) {
                Map<String, Object> totalSeriesData = new HashMap<>();

                // 기존 타임스탬프와 데이터 복사
                List<Long> timestamps = new ArrayList<>(totalData.getTimestamps());
                List<Integer> success = new ArrayList<>(totalData.getSuccess());
                List<Integer> fail = new ArrayList<>(totalData.getFail());
                List<Integer> timeout = new ArrayList<>(totalData.getTimeout());
                List<Integer> syserror = new ArrayList<>(totalData.getSyserror());

                // 현재 전체 합계 계산
                int totalSuccess = 0;
                int totalFail = 0;
                int totalTimeout = 0;
                int totalSyserror = 0;

                for (String serviceType : currentTransactions.keySet()) {
                    MemStaticsVo stats = currentTransactions.get(serviceType);
                    if (stats != null) {
                        totalSuccess += stats.getProcTotal() - stats.getErrorTotal()
                                - stats.getTimeoutTotal() - stats.getSysErrorTotal();
                        totalFail += stats.getErrorTotal();
                        totalTimeout += stats.getTimeoutTotal();
                        totalSyserror += stats.getSysErrorTotal();
                    }
                }

                // 마지막 데이터와 현재 시간이 2초 이상 차이가 나면 현재 값 추가
                boolean shouldAddCurrentData = true;
                if (!timestamps.isEmpty() && (currentTimestamp - timestamps.get(timestamps.size() - 1)) < 2000) {
                    shouldAddCurrentData = false;
                }

                if (shouldAddCurrentData) {
                    timestamps.add(currentTimestamp);
                    success.add(totalSuccess);
                    fail.add(totalFail);
                    timeout.add(totalTimeout);
                    syserror.add(totalSyserror);
                }

                totalSeriesData.put("timestamps", timestamps);
                totalSeriesData.put("success", success);
                totalSeriesData.put("fail", fail);
                totalSeriesData.put("timeout", timeout);
                totalSeriesData.put("syserror", syserror);
                timeSeriesData.put("TOTAL", totalSeriesData);
            } else {
                // 전체 데이터가 없는 경우, 더미 데이터 생성은 제거
                Map<String, Object> emptyData = new HashMap<>();
                emptyData.put("timestamps", new ArrayList<>());
                emptyData.put("success", new ArrayList<>());
                emptyData.put("fail", new ArrayList<>());
                emptyData.put("timeout", new ArrayList<>());
                emptyData.put("syserror", new ArrayList<>());
                timeSeriesData.put("TOTAL", emptyData);
            }

            response.put("timeSeriesData", timeSeriesData);
            response.put("minutes", minutes);
            response.put("timestamp", System.currentTimeMillis());

            return response;
        } catch (Exception e) {
            log.error("트랜잭션 시계열 정보 조회 중 오류 발생", e);
            response.put("error", "트랜잭션 시계열 정보 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * 서버 리소스 시계열 데이터 제공 API
     * 특정 서버의 CPU, 메모리, 디스크 사용량 시계열 데이터를 제공합니다.
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=server-resource")
    @ResponseBody
    public Map<String, Object> getServerResourceData(
            @RequestParam String hostname,
            @RequestParam(required = false, defaultValue = "7") int count) {
        Map<String, Object> response = new HashMap<>();
        try {
            // 서버 리소스 시계열 데이터 조회
            ThroughputCalculationService.ServerResourceData resourceData =
                    throughputCalculationService.getServerResourceData(hostname, count);

            // 응답 데이터 구성
            Map<String, Object> data = new HashMap<>();
            data.put("hostname", hostname);
            data.put("timestamps", resourceData.getTimestamps());
            data.put("cpu", resourceData.getCpu());
            data.put("memory", resourceData.getMemory());
            data.put("disk", resourceData.getDisk());

            response.put("data", data);
            return response;
        } catch (Exception e) {
            log.error("서버 리소스 시계열 데이터 조회 중 오류 발생", e);
            response.put("error", "서버 리소스 시계열 데이터 조회 중 오류가 발생했습니다.");
            return response;
        }
    }

    /**
     * SMS 장애 통보 정보를 조회합니다.
     * @return SMS 장애 통보 정보
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=sms-notification")
    @ResponseBody
    public Map<String, Object> getSmsNotification() {
        Map<String, Object> result = new HashMap<>();
        List<SmsVO> totalSmsList = new ArrayList<>();

        try {

            List<DataSourceType> servers = DataSourceTypeManager.getOnlineDataSourceTypes();

            // GW 추가
            if( DataSourceTypeManager.getDataSourceType("FGW") != null ){
                servers.add(DataSourceTypeManager.getDataSourceType("FGW"));
            }

            if( DataSourceTypeManager.getDataSourceType("CGW") != null ){
                servers.add(DataSourceTypeManager.getDataSourceType("CGW"));
            }

            for (DataSourceType d : servers) {
                DataSourceContextHolder.setDataSourceType(d);
                List ipList = eaiServerInfoService.getEaiServerIpListDB();
                List<SmsVO> smsList = dashboardService.findSmsList(ipList, d.getName());
                totalSmsList.addAll(smsList);
            }

            // SmsVO 목록을 SmsNotificationDto 목록으로 변환
            List<SmsNotificationDto> smsNotificationDtoList = smsNotificationMapper.mapToSmsNotificationDtoList(totalSmsList);

            result.put("success", true);
            result.put("data", smsNotificationDtoList);
        } catch (Exception e) {
            log.error("SMS 장애 통보 정보 조회 중 오류 발생", e);
            result.put("success", false);
            result.put("message", "SMS 장애 통보 정보 조회 중 오류가 발생했습니다.");
        }

        return result;
    }

    /**
     * Get socket status data
     * @param serverName Optional server name filter
     * @param adapterGroup Optional adapter group filter
     * @return SocketStatusDTO with all socket status data
     */
    @RequestMapping(value = "/socket-status")
    @ResponseBody
    public ResponseEntity<SocketStatusDTO> getSocketStatus(
            @RequestParam(value = "serverName", required = false) String serverName,
            @RequestParam(value = "adapterGroup", required = false) String adapterGroup) {

        SocketStatusDTO result = socketMonitorService.getSocketStatus(serverName, adapterGroup);
        return ResponseEntity.ok(result);
    }

    /**
     * Get socket process data
     * @param serverName Optional server name filter
     * @param adapterGroup Optional adapter group filter
     * @return SocketProcessDTO with all socket process data
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=socket-process")
    @ResponseBody
    public ResponseEntity<SocketProcessDTO> getSocketProcess(
            @RequestParam(value = "serverName", required = false) String serverName,
            @RequestParam(value = "adapterGroup", required = false) String adapterGroup) {

        SocketProcessDTO result = socketMonitorService.getSocketProcess(serverName, adapterGroup);
        return ResponseEntity.ok(result);
    }

    /**
     * Get combined socket data (both status and process)
     * @param serverName Optional server name filter
     * @param adapterGroup Optional adapter group filter
     * @return Map containing both socket status and process data
     */
    @RequestMapping(path = "/modern-dashboard-api.do", params = "type=socket-combined")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getCombinedSocketData(
            @RequestParam(value = "serverName", required = false) String serverName,
            @RequestParam(value = "adapterGroup", required = false) String adapterGroup) {

        Map<String, Object> result = socketMonitorService.getCombinedSocketData(serverName, adapterGroup);
        return ResponseEntity.ok(result);
    }

    /**
     * 거래현황 시계열 데이터 조회
     * @param seconds 조회할 초 단위 기간 (기본값 60초, 최대 120초)
     * @return 시계열 데이터
     */
    @GetMapping(path = "/modern-dashboard-api.do", params = "type=timeseries")
    public ResponseEntity<Map<String, Object>> getTimeSeriesData(
            @RequestParam(defaultValue = "60") int seconds) {

        TransactionSummaryService.TimeSeriesData data = transactionSummaryService.getTimeSeriesData(seconds);

        // 전체 기간 동안의 합계 계산
        Map<String, Integer> totals = data.calculateTotalCounts();

        // 데이터 포인트들을 오류 건수 -> 정상 건수 순으로 정렬
        List<Map<String, Object>> sortedDataPoints = IntStream.range(0, data.getTimestamps().size())
                .mapToObj(i -> {
                    Map<String, Object> point = new HashMap<>();
                    point.put("timestamp", data.getTimestamps().get(i));
                    point.put("error", data.getError().get(i));
                    point.put("success", data.getSuccess().get(i));
                    point.put("avgTime", data.getAvgTime().get(i));
                    return point;
                })
                .sorted((a, b) -> {
                    // 1차: 오류 건수 내림차순
                    int errorCompare = ((Integer)b.get("error")).compareTo((Integer)a.get("error"));
                    if (errorCompare != 0) return errorCompare;
                    // 2차: 정상 건수 내림차순
                    return ((Integer)b.get("success")).compareTo((Integer)a.get("success"));
                })
                .collect(Collectors.toList());

        Map<String, Object> response = new HashMap<>();
        response.put("seconds", seconds);
        response.put("totalError", totals.get("error"));
        response.put("totalSuccess", totals.get("success"));
        response.put("dataPoints", sortedDataPoints);

        return ResponseEntity.ok(response);
    }
}