package com.eactive.eai.custom.inflow;

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

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.DualCustomBucket;
import com.eactive.eai.manage.inflow.GroupBucketStatusDTO;
import com.eactive.eai.manage.inflow.TargetBucketStatusDTO;

/**
 * 클라이언트 버킷 상태 조회 서비스.
 *
 * ClientDualInflowControlManager 가 활성화된 경우에만 동작한다.
 */
@Service
public class ClientInflowTargetBucketService {

    public TargetBucketStatusDTO getClientBucketStatus(String clientId) {
        ClientDualInflowControlManager manager = getClientDualManager();
        if (manager == null) return null;
        DualCustomBucket bucket = manager.getClientBucket(clientId);
        if (bucket == null) return null;
        return toDto(clientId, "CLIENT", bucket);
    }

    public List<TargetBucketStatusDTO> getAllClientBucketStatus() {
        ClientDualInflowControlManager manager = getClientDualManager();
        if (manager == null) return new ArrayList<>();
        return toDtoList("CLIENT", manager.getClientBucketMap());
    }

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

    private TargetBucketStatusDTO toDto(String targetId, String targetType, DualCustomBucket bucket) {
        InflowTargetVO vo = bucket.getInflowTargetVo();
        List<GroupBucketStatusDTO.BucketInfo> buckets = new ArrayList<>();

        if (vo.getThresholdPerSecond() > 0) {
            long capacity  = vo.getThresholdPerSecond();
            long available = bucket.getPerSecondAvailableTokens();
            if (available < 0) available = capacity;
            buckets.add(new GroupBucketStatusDTO.BucketInfo(
                    "perSecond", capacity, Math.min(available, capacity), "SEC"));
        }

        if (vo.getThreshold() > 0) {
            long capacity  = vo.getThreshold();
            long available = bucket.getThresholdAvailableTokens();
            if (available < 0) available = capacity;
            buckets.add(new GroupBucketStatusDTO.BucketInfo(
                    "threshold", capacity, Math.min(available, capacity), vo.getThresholdTimeUnit()));
        }

        TargetBucketStatusDTO dto = new TargetBucketStatusDTO();
        dto.setTargetId(targetId);
        dto.setTargetType(targetType);
        dto.setActivate(vo.isActivate());
        dto.setBuckets(buckets);
        return dto;
    }

    private List<TargetBucketStatusDTO> toDtoList(String targetType, Map<String, DualCustomBucket> bucketMap) {
        List<TargetBucketStatusDTO> result = new ArrayList<>();
        for (Map.Entry<String, DualCustomBucket> entry : bucketMap.entrySet()) {
            result.add(toDto(entry.getKey(), targetType, entry.getValue()));
        }
        return result;
    }
}
