package com.eactive.eai.manage.inflow;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.eactive.eai.common.inflow.AbstractInflowControlManager;
import com.eactive.eai.common.inflow.InflowControlUtil;
import com.eactive.eai.common.inflow.InflowTargetVO;
import com.eactive.eai.common.inflow.dual.DualInflowControlManager;

@Service
public class InflowTargetMetricService {

    // -------------------------------------------------------------------------
    // 어댑터
    // -------------------------------------------------------------------------

    public TargetMetricDTO getAdapterMetric(String adapterId) {
        DualInflowControlManager manager = getDualManager();
        if (manager == null) return null;
        InflowTargetVO vo = manager.getAdapterInflowThreashold(adapterId);
        if (vo == null) return null;
        return buildDTO(adapterId, "ADAPTER", vo, manager.getAdapterMetrics(adapterId));
    }

    public List<TargetMetricDTO> getAllAdapterMetrics() {
        DualInflowControlManager manager = getDualManager();
        if (manager == null) return new ArrayList<>();
        List<TargetMetricDTO> result = new ArrayList<>();
        for (String id : manager.getAdapterAllKeys()) {
            TargetMetricDTO dto = getAdapterMetric(id);
            if (dto != null) result.add(dto);
        }
        return result;
    }

    public boolean resetAdapterMetric(String adapterId) {
        DualInflowControlManager manager = getDualManager();
        if (manager == null) return false;
        if (manager.getAdapterInflowThreashold(adapterId) == null) return false;
        manager.resetAdapterMetrics(adapterId);
        return true;
    }

    public void resetAllAdapterMetrics() {
        DualInflowControlManager manager = getDualManager();
        if (manager != null) manager.resetAllAdapterMetrics();
    }

    // -------------------------------------------------------------------------
    // 인터페이스
    // -------------------------------------------------------------------------

    public TargetMetricDTO getInterfaceMetric(String interfaceId) {
        DualInflowControlManager manager = getDualManager();
        if (manager == null) return null;
        InflowTargetVO vo = manager.getInterfaceInflowThreashold(interfaceId);
        if (vo == null) return null;
        return buildDTO(interfaceId, "INTERFACE", vo, manager.getInterfaceMetrics(interfaceId));
    }

    public List<TargetMetricDTO> getAllInterfaceMetrics() {
        DualInflowControlManager manager = getDualManager();
        if (manager == null) return new ArrayList<>();
        List<TargetMetricDTO> result = new ArrayList<>();
        for (String id : manager.getInterfaceAllKeys()) {
            TargetMetricDTO dto = getInterfaceMetric(id);
            if (dto != null) result.add(dto);
        }
        return result;
    }

    public boolean resetInterfaceMetric(String interfaceId) {
        DualInflowControlManager manager = getDualManager();
        if (manager == null) return false;
        if (manager.getInterfaceInflowThreashold(interfaceId) == null) return false;
        manager.resetInterfaceMetrics(interfaceId);
        return true;
    }

    public void resetAllInterfaceMetrics() {
        DualInflowControlManager manager = getDualManager();
        if (manager != null) manager.resetAllInterfaceMetrics();
    }

    // -------------------------------------------------------------------------
    // Private helpers
    // -------------------------------------------------------------------------

    protected DualInflowControlManager getDualManager() {
        AbstractInflowControlManager base = InflowControlUtil.getInflowControlManager();
        return (base instanceof DualInflowControlManager) ? (DualInflowControlManager) base : null;
    }

    private TargetMetricDTO buildDTO(String targetId, String targetType,
                                     InflowTargetVO vo,
                                     DualInflowControlManager.TargetMetrics m) {
        TargetMetricDTO dto = new TargetMetricDTO();
        dto.setTargetId(targetId);
        dto.setTargetType(targetType);
        dto.setActivate(vo.isActivate());

        if (m != null) {
            long allowed = m.allowed.get();
            long rejPs   = m.rejectedPerSecond.get();
            long rejTh   = m.rejectedThreshold.get();
            long total   = allowed + rejPs + rejTh;
            dto.setAllowed(allowed);
            dto.setRejectedPerSecond(rejPs);
            dto.setRejectedThreshold(rejTh);
            dto.setTotalRequests(total);
            dto.setRejectRatio(total > 0
                ? Math.round((double)(rejPs + rejTh) / total * 10000) / 100.0
                : 0.0);
            dto.setLastResetTime(m.lastResetTime);
        }
        return dto;
    }
}
