package com.eactive.eai.custom.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;
import com.eactive.eai.manage.inflow.TargetMetricDTO;

@Service
public class ClientInflowTargetMetricService {

    public TargetMetricDTO getClientMetric(String clientId) {
        ClientDualInflowControlManager manager = getClientDualManager();
        if (manager == null) return null;
        InflowTargetVO vo = manager.getClientInflowThreshold(clientId);
        if (vo == null) return null;
        return buildDTO(clientId, "CLIENT", vo, manager.getClientMetrics(clientId));
    }

    public List<TargetMetricDTO> getAllClientMetrics() {
        ClientDualInflowControlManager manager = getClientDualManager();
        if (manager == null) return new ArrayList<>();
        List<TargetMetricDTO> result = new ArrayList<>();
        for (String id : manager.getClientBucketMap().keySet()) {
            TargetMetricDTO dto = getClientMetric(id);
            if (dto != null) result.add(dto);
        }
        return result;
    }

    public boolean resetClientMetric(String clientId) {
        ClientDualInflowControlManager manager = getClientDualManager();
        if (manager == null) return false;
        if (manager.getClientInflowThreshold(clientId) == null) return false;
        manager.resetClientMetrics(clientId);
        return true;
    }

    public void resetAllClientMetrics() {
        ClientDualInflowControlManager manager = getClientDualManager();
        if (manager != null) manager.resetAllClientMetrics();
    }

    protected ClientDualInflowControlManager getClientDualManager() {
        AbstractInflowControlManager base = InflowControlUtil.getInflowControlManager();
        return (base instanceof ClientDualInflowControlManager) ? (ClientDualInflowControlManager) 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;
    }
}
