package com.docus.server.common.process;

import com.docus.core.util.Func;
import com.docus.log.context.TrackContext;
import com.docus.log.processor.AbstractProcessor;
import com.docus.server.common.netty.server.TerminalToChannelCacheMap;
import com.docus.server.dto.scheduling.management.schcollectrecord.EditSchCollectRecordDTO;
import com.docus.server.dto.scheduling.management.schterminator.EditSchTerminatorDTO;
import com.docus.server.dto.scheduling.management.schterminator.NettyTerminatorDTO;
import com.docus.server.enums.BusyStateEnum;
import com.docus.server.enums.RetryTaskEnum;
import com.docus.server.enums.StateEnum;
import com.docus.server.service.ISchCollectRecordRetryLogService;
import com.docus.server.service.ISchCollectRecordService;
import com.docus.server.service.ISchTerminatorService;
import com.docus.server.vo.scheduling.management.schcollectrecord.SchCollectRecordVO;
import com.docus.server.vo.scheduling.management.schcollectrecordretrylog.SchCollectRecordRetryLogVO;
import com.docus.server.vo.scheduling.management.schterminator.SchTerminatorVO;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * channel 管理
 */
public class ChannelProcessor extends AbstractProcessor {
    @Resource
    private TerminalToChannelCacheMap channelRepository;
    @Resource
    private ISchTerminatorService iSchTerminatorService;
    @Resource
    private ISchCollectRecordService iSchCollectRecordService;
    @Resource
    private ISchCollectRecordRetryLogService iSchCollectRecordRetryLogService;

    @Override
    protected Object doProcess(TrackContext context) {
        String group = context.getGroup();

        switch (group) {
            case "SchCollectRecordController-edit":
                doSchCollectRecordControllerEdit(context);
                break;
            case "SchTerminatorController":
                doSchTerminatorController(context);
                break;
            case "RedisKeyExpirationService-expired":
                doRedisKeyExpired(context);
                break;
            default:
                return null;
        }

        return null;
    }

    private Object doRedisKeyExpired(TrackContext context) {
        boolean error = context.isError();
        String expireKey = (String) context.getArgs()[0];

        String recordId = expireKey.substring(expireKey.lastIndexOf(":") + 1);

        if (!error) {

            if (expireKey.startsWith("schCollectorRecord:isRetryTask:expireKey:")) {
                retryTask(recordId);
            }
            if (expireKey.startsWith("schCollectorRecord:noRetryTask:expireKey:")) {
                noRetryTask(recordId);

            }
        }
        return null;
    }

    private void doSchCollectRecordControllerEdit(TrackContext context) {
        logCollectRecord(context);
    }

    private boolean doSchTerminatorController(TrackContext context) {
        return logTerminator(context);
    }

    private boolean logCollectRecord(TrackContext context) {
        boolean error = context.isError();

        EditSchCollectRecordDTO collectRecordDTO = (EditSchCollectRecordDTO) context.getArgs()[0];

        if (!error) {

            if (RetryTaskEnum.NO_RETRY_TASK.equals(collectRecordDTO.getIsRetryTask())) {

                noRetryTask(String.valueOf(collectRecordDTO.getId()));

            } else if (RetryTaskEnum.RETRY_TASK.equals(collectRecordDTO.getIsRetryTask())) {

                retryTask(String.valueOf(collectRecordDTO.getId()));

            }

        }
        return error;

    }

    private void retryTask(String recordLogId) {
        SchCollectRecordRetryLogVO retryLogVO = iSchCollectRecordRetryLogService.findById(recordLogId);

        updateTerminatorState(retryLogVO.getTerminatorId(), retryLogVO.getTaskExecState());

    }

    private void noRetryTask(String recordId) {

        SchCollectRecordVO schCollectRecordVO = iSchCollectRecordService.findById(recordId);

        updateTerminatorState(schCollectRecordVO.getTerminatorId(), schCollectRecordVO.getTaskExecState());
    }

    private void updateTerminatorState(Long terminatorId, StateEnum taskExecState) {
        SchTerminatorVO schTerminatorVO = iSchTerminatorService.findById(String.valueOf(terminatorId));

        NettyTerminatorDTO nettyTerminatorDTO = channelRepository.getTerminatorByIp(String.valueOf(schTerminatorVO.getTerminatorIp()));

        if (Func.isEmpty(nettyTerminatorDTO)) {
            return;
        }

        List<StateEnum> stateEnums = Arrays.asList(StateEnum.values());

        if (stateEnums.contains(taskExecState)) {
            nettyTerminatorDTO.setBusyState(BusyStateEnum.IDLE);
        }
    }

    private boolean logTerminator(TrackContext context) {
        boolean error = context.isError();
        EditSchTerminatorDTO terminatorDTO = (EditSchTerminatorDTO) context.getArgs()[0];
        if (!error) {
            SchTerminatorVO terminatorVO = iSchTerminatorService.findById(String.valueOf(terminatorDTO.getId()));

            NettyTerminatorDTO nettyTerminatorDTO = channelRepository.getTerminatorByIp(terminatorVO.getTerminatorIp());

            if (Func.isNotBlank(terminatorDTO.getOnlyCollectorIds())) {
                List<String> onlyList = Arrays.stream(terminatorDTO.getOnlyCollectorIds().split(",")).map(String::valueOf).collect(Collectors.toList());
                nettyTerminatorDTO.setOnlyCollectorIds(onlyList);
            }
            if (Func.isNotBlank(terminatorDTO.getPriorityCollectorIds())) {
                List<String> priList = Arrays.stream(terminatorDTO.getPriorityCollectorIds().split(",")).map(String::valueOf).collect(Collectors.toList());
                nettyTerminatorDTO.setPriorityCollectorIds(priList);
            }
        }
        return error;
    }
}
