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

import com.eactive.eai.rms.common.datasource.DataSourceType;
import com.eactive.eai.rms.onl.dashboard.modern.dto.*;
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 org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 대시보드 데이터 매퍼
 * VO 객체를 DTO로 변환하는 역할을 담당합니다.
 */
@Component
public class DashboardDataMapper {

    /**
     * EAIEngineStatusVo를 ServerStatusDTO로 변환
     * 서버 상태 정보를 포함합니다.
     */
    public ServerStatusDTO fromEAIEngineStatusVo(EAIEngineStatusVo vo) {
        ServerStatusDTO dto = new ServerStatusDTO();

        if (vo == null) {
            return dto;
        }

        // 서버 기본 정보 설정
        dto.setName(vo.getServerName() != null ? vo.getServerName() : vo.getHostName());
        dto.setText(vo.getService());

        // 서버 상태 설정 (serverStateImage: 0=중지/에러, 1=경고, 2=정상)
        switch (vo.getServerStateImage()) {
            case 0:
                dto.setStatus("error");
                break;
            case 1:
                dto.setStatus("warning");
                break;
            case 2:
                dto.setStatus("normal");
                break;
            default:
                dto.setStatus("unknown");
        }

        // 리소스 사용률 설정
        if (vo.getHeapSizeCurrent() > 0) {
            dto.setCpu((int)(100 - (vo.getHeapFreeCurrent() * 100) / vo.getHeapSizeCurrent()));
        } else {
            dto.setCpu(0);
        }
        dto.setMemory(vo.getHeapFreePercent() > 0 ? 100 - vo.getHeapFreePercent() : 0);
        dto.setDisk(vo.getJmsFileStoreUseAge());

        // 인스턴스 정보 설정
        List<InstanceDTO> instances = new ArrayList<>();
        InstanceDTO instance = new InstanceDTO();
        instance.setId(vo.getInstanceName());

        // 인스턴스 상태 설정
        switch (vo.getServerStateImage()) {
            case 0:
                instance.setStatus("error");
                break;
            case 1:
                instance.setStatus("warning");
                break;
            case 2:
                instance.setStatus("normal");
                break;
            default:
                instance.setStatus("inactive");
        }

        // 처리량 정보 설정
        instance.setThroughput(vo.getPendingRequestCurrentCount() + "/s");

        instances.add(instance);
        dto.setInstances(instances);

        return dto;
    }

    /**
     * HostStatusVo를 ServerStatusDTO로 변환
     * 호스트 상태 정보를 포함합니다.
     */
    public ServerStatusDTO fromHostStatusVo(HostStatusVo vo) {
        ServerStatusDTO dto = new ServerStatusDTO();

        if (vo == null) {
            return dto;
        }

        dto.setName(vo.getHostName());
        dto.setText(vo.getHostName());
        dto.setCpu(vo.getCpu());
        dto.setMemory(vo.getMemory());
        dto.setDisk(vo.getDisk());
        dto.setStatus(getStatusFromUsage(vo.getCpu(), vo.getMemory(), vo.getDisk()));

        // 인스턴스 리스트는 다른 곳에서 채워질 것임
        dto.setInstances(new ArrayList<>());

        return dto;
    }

    /**
     * AdaptersVO를 AdapterStatusDTO 목록으로 변환
     * Socket, HTTP 어댑터 정보만 포함합니다.
     */
    public List<AdapterStatusDTO> fromAdaptersVO(AdaptersVO vo) {
        List<AdapterStatusDTO> dtoList = new ArrayList<>();

        if (vo == null) {
            return dtoList;
        }

        // Socket 어댑터 상태 (Socket과 Socket2를 하나로 통합)
        AdapterStatusDTO socketDTO = new AdapterStatusDTO();
        socketDTO.setServerName(vo.getHostName());
        socketDTO.setInstanceId(vo.getInstanceName());
        socketDTO.setAdapterType("Socket");

        // Socket과 Socket2의 상태 중 더 심각한 상태를 선택
        int socketStatus = vo.getSocket(3);
        int socket2Status = vo.getSocket2(3);
        int combinedStatus = Math.min(socketStatus, socket2Status); // 낮은 값이 더 심각한 상태
        socketDTO.setStatus(getStatusTextFromCode(combinedStatus));

        // Socket과 Socket2의 카운트를 합산
        socketDTO.setTotalCount(vo.getSocket(0) + vo.getSocket2(0));
        socketDTO.setRunningCount(vo.getSocket(1) + vo.getSocket2(1));
        socketDTO.setStopCount(vo.getSocket(2) + vo.getSocket2(2));
        dtoList.add(socketDTO);

        // HTTP 어댑터 상태
        AdapterStatusDTO httpDTO = new AdapterStatusDTO();
        httpDTO.setServerName(vo.getHostName());
        httpDTO.setInstanceId(vo.getInstanceName());
        httpDTO.setAdapterType("HTTP");
        httpDTO.setStatus(getStatusTextFromCode(vo.getHttp(3)));
        httpDTO.setTotalCount(vo.getHttp(0));
        httpDTO.setRunningCount(vo.getHttp(1));
        httpDTO.setStopCount(vo.getHttp(2));
        dtoList.add(httpDTO);

        return dtoList;
    }

    /**
     * 상태 코드를 텍스트로 변환
     */
    private String getStatusTextFromCode(int statusCode) {
        switch (statusCode) {
            case 0:
                return "error";
            case 1:
                return "warning";
            case 2:
                return "normal";
            case 3:
                return "inactive";
            default:
                return "unknown";
        }
    }

    /**
     * MemStaticsVo를 TransactionDTO로 변환
     * 트랜잭션 통계 정보를 포함합니다.
     */
    public TransactionDTO fromMemStaticsVo(MemStaticsVo vo, String serviceType) {
        TransactionDTO dto = new TransactionDTO();

        if (vo == null) {
            return dto;
        }

        dto.setType(serviceType); // 서비스 타입을 파라미터로 받아서 설정
        dto.setSuccess(vo.getProcTotal() - vo.getTimeoutTotal() - vo.getErrorTotal() - vo.getSysErrorTotal());
        dto.setTimeout(vo.getTimeoutTotal());
        dto.setFail(vo.getErrorTotal());
        dto.setSyserror(vo.getSysErrorTotal());

        return dto;
    }

    /**
     * DB 저장소에서 가져온 피크 성능 문자열을 PeakPerformanceDTO로 변환
     */
    public PeakPerformanceDTO fromPeakPerformanceString(String peakDataStr, String type) {
        PeakPerformanceDTO dto = new PeakPerformanceDTO();

        if (peakDataStr == null || peakDataStr.isEmpty()) {
            return dto;
        }

        String[] fields = peakDataStr.split(",");
        if (fields.length < 4) {
            return dto;
        }

        dto.setServiceType(fields[0]);   // 서비스 유형
        dto.setDate(fields[1]);          // 날짜

        try {
            dto.setTransactionCount(Integer.parseInt(fields[2]));   // 처리 건수
            if( "--".equals(fields[3]) ){
                dto.setTps(0);
            } else {
                dto.setTps(Integer.parseInt(fields[3]));                // TPS
            }
        } catch (NumberFormatException e) {
            dto.setTransactionCount(0);
            dto.setTps(0);
        }

        return dto;
    }

    /**
     * 일괄 전송 처리 데이터를 BatchProcessDTO로 변환
     * @param csvData 형식: 송신성공,수신성공,송신에러,수신에러,송신대기,수신대기
     */
    public BatchProcessDTO fromBatchProcessString(String serviceType, String csvData) {
        BatchProcessDTO dto = new BatchProcessDTO();
        dto.setServiceType(serviceType);
        dto.setProcBatch(csvData); // 원본 CSV 데이터 설정

        return dto;
    }

    /**
     * 서버 인스턴스 정보를 포함하는 서버 상태 DTO 생성
     */
    public ServerStatusDTO createServerStatus(DataSourceType server, Map<String, Object> serverData) {
        ServerStatusDTO dto = new ServerStatusDTO();
        dto.setName(server.getName());
        dto.setText(server.getText());

        // CPU, 메모리, 디스크 사용률 설정
        if (serverData.containsKey("cpu")) {
            dto.setCpu((int) serverData.get("cpu"));
        }
        if (serverData.containsKey("memory")) {
            dto.setMemory((int) serverData.get("memory"));
        }
        if (serverData.containsKey("disk")) {
            dto.setDisk((int) serverData.get("disk"));
        }

        // 서버 상태 설정
        dto.setStatus(getStatusFromUsage(dto.getCpu(), dto.getMemory(), dto.getDisk()));

        // 인스턴스 목록 설정
        List<InstanceDTO> instances = new ArrayList<>();
        if (serverData.containsKey("instances")) {
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> instanceDataList = (List<Map<String, Object>>) serverData.get("instances");

            for (Map<String, Object> instanceData : instanceDataList) {
                InstanceDTO instance = new InstanceDTO();

                if (instanceData.containsKey("id")) {
                    instance.setId((String) instanceData.get("id"));
                }
                if (instanceData.containsKey("status")) {
                    instance.setStatus((String) instanceData.get("status"));
                }
                if (instanceData.containsKey("throughput")) {
                    instance.setThroughput((String) instanceData.get("throughput"));
                }

                instances.add(instance);
            }
        }

        dto.setInstances(instances);

        return dto;
    }

    /**
     * 사용률에 따른 상태 반환
     */
    private String getStatusFromUsage(int cpu, int memory, int disk) {
        if (cpu > 90 || memory > 90 || disk > 90) {
            return "error";
        } else if (cpu > 70 || memory > 70 || disk > 70) {
            return "warning";
        } else {
            return "normal";
        }
    }

    /**
     * 서버 이름과 인스턴스 목록을 기반으로 인스턴스별 상태를 생성
     */
    public List<Map<String, Object>> createInstanceStatusList(String serverName, List<EAIEngineStatusVo> engineStatusList) {
        List<Map<String, Object>> instanceStatusList = new ArrayList<>();

        for (EAIEngineStatusVo engineStatus : engineStatusList) {
            Map<String, Object> instanceStatus = new HashMap<>();
            instanceStatus.put("serverName", serverName);
            instanceStatus.put("instanceName", engineStatus.getInstanceName());
            instanceStatus.put("status", getStatusTextFromCode(engineStatus.getServerStateImage()));
            instanceStatus.put("cpu", engineStatus.getHeapFreePercent() > 0 ? 100 - engineStatus.getHeapFreePercent() : 0);
            instanceStatus.put("memory", engineStatus.getHeapFreePercent() > 0 ? engineStatus.getHeapFreePercent() : 0);
            instanceStatus.put("disk", engineStatus.getJmsFileStoreUseAge());
            instanceStatus.put("throughput", engineStatus.getPendingRequestCurrentCount() + "/s");

            instanceStatusList.add(instanceStatus);
        }

        return instanceStatusList;
    }

    /**
     * AdaptersVO 목록을 AdapterStatusSummaryContainerDTO로 변환
     * 어댑터 유형별 상태 집계 정보를 제공합니다.
     */
    public AdapterStatusSummaryContainerDTO fromAdaptersVOList(List<AdaptersVO> adaptersList) {
        AdapterStatusSummaryContainerDTO container = new AdapterStatusSummaryContainerDTO();

        if (adaptersList == null || adaptersList.isEmpty()) {
            return container;
        }

        // 각 어댑터의 상태를 집계
        for (AdaptersVO vo : adaptersList) {
            if (vo == null) continue;

            // Socket 어댑터 상태 집계 (Socket과 Socket2를 하나로 통합)
            container.getAdapterSummary("Socket").incrementStatusCount(vo.getSocket(3));
            container.getAdapterSummary("Socket").incrementStatusCount(vo.getSocket2(3));

            // HTTP 어댑터 상태 집계
            container.getAdapterSummary("HTTP").incrementStatusCount(vo.getHttp(3));
        }

        // 전체 상태 업데이트
        container.updateOverallStatus();

        return container;
    }
}