package com.usky.rule.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.usky.common.core.bean.CommonPage;
import com.usky.common.core.exception.BusinessException;
import com.usky.common.mybatis.core.AbstractCrudService;
import com.usky.common.security.utils.SecurityUtils;
import com.usky.rule.domain.RuleEngineLog;
import com.usky.rule.mapper.RuleEngineLogMapper;
import com.usky.rule.service.RuleEngineLogService;
import com.usky.rule.util.JsonUtil;
import com.usky.rule.vo.RuleEngineContent;
import com.usky.rule.vo.RuleEngineLogPageRequest;
import com.usky.rule.vo.log.*;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class RuleEngineLogServiceImpl extends AbstractCrudService<RuleEngineLogMapper, RuleEngineLog> implements RuleEngineLogService {
    private final RuleEngineLogMapper ruleEngineLogMapper;

    private final Map<String, RuleEngineLogSerialization<?>> serializationMap = new HashMap();

    public RuleEngineLogServiceImpl(RuleEngineLogMapper ruleEngineLogMapper) {
        this.ruleEngineLogMapper = ruleEngineLogMapper;
    }

    @PostConstruct
    public void initSerializationMap() {
        TriggerCronSerialization triggerCronSerialization = new TriggerCronSerialization();
        TriggerDeviceSerialization triggerDeviceSerialization = new TriggerDeviceSerialization();
        this.serializationMap.put(triggerDeviceSerialization.getType(), triggerDeviceSerialization);
        this.serializationMap.put(triggerCronSerialization.getType(), triggerCronSerialization);
        ConstraintCronSerialization constraintCronSerialization = new ConstraintCronSerialization();
        ConstraintDeviceSerialization constraintDeviceSerialization = new ConstraintDeviceSerialization();
        this.serializationMap.put(constraintDeviceSerialization.getType(), constraintDeviceSerialization);
        this.serializationMap.put(constraintCronSerialization.getType(), constraintCronSerialization);
        ActionAlarmEventSerialization actionAlarmEventSerialization = new ActionAlarmEventSerialization();
//        ActionWorkOrderSerialization actionWorkOrderSerialization = new ActionWorkOrderSerialization();
        ActionControlSerialization actionControlSerialization = new ActionControlSerialization();
        this.serializationMap.put(actionControlSerialization.getType(), actionControlSerialization);
        this.serializationMap.put(actionAlarmEventSerialization.getType(), actionAlarmEventSerialization);
//        this.serializationMap.put(actionWorkOrderSerialization.getType(), actionWorkOrderSerialization);
    }

    @Override
    public void add(RuleEngineLog log) {
        ruleEngineLogMapper.insert(log);
    }

    @Override
    public void update(RuleEngineLog log) {
        ruleEngineLogMapper.updateById(log);
    }

    @Override
    public void remove(Long id) {
        ruleEngineLogMapper.deleteById(id);
    }

    @Override
    public RuleEngineContent getById(Long id) {
        RuleEngineLog ruleEngineLog =  ruleEngineLogMapper.selectById(id);
        if(ruleEngineLog==null){
            return null;
        }

        String detail = ruleEngineLog.getDetail();
        RuleEngineDetailLog ruleEngineDetailLog = (RuleEngineDetailLog) JsonUtil.toObject(detail, RuleEngineDetailLog.class);
        List<BaseLog> triggerLogs = ruleEngineDetailLog.getTriggers();
        List<BaseLog> constraintLogs = ruleEngineDetailLog.getConstraints();
        List<BaseLog> actionLogs = ruleEngineDetailLog.getActions();
        RuleEngineContent ruleEngineContent = new RuleEngineContent();
        RuleEngineContent.Trigger trigger = new RuleEngineContent.Trigger();
        trigger.setAutoTrigger(ruleEngineLog.getAutoTrigger() + "");
        trigger.setType(ruleEngineLog.getTriggerType());
        if (!CollectionUtils.isEmpty(triggerLogs)) {
            BaseLog triggerLog = (BaseLog)triggerLogs.get(0);
            Content triggerContent = ((RuleEngineLogSerialization)this.serializationMap.get("trigger:" + triggerLog.getType())).toContent(triggerLog.getDetail());
            trigger.setContent(triggerContent.getContent());
            trigger.setTime(triggerContent.getTime());
        }

        ruleEngineContent.setTrigger(trigger);
        List<RuleEngineContent.Constraints> constraints = new ArrayList();
        if (!CollectionUtils.isEmpty(constraintLogs)) {
            for(BaseLog constraintLog : constraintLogs) {
                RuleEngineContent.Constraints constraint = new RuleEngineContent.Constraints();
                Content constraintContent = ((RuleEngineLogSerialization)this.serializationMap.get("constraint:" + constraintLog.getType())).toContent(constraintLog.getDetail());
                constraint.setContent(constraintContent.getContent());
                constraint.setType(constraintLog.getType());
                constraints.add(constraint);
            }
        }

        ruleEngineContent.setConstraints(constraints);
        List<RuleEngineContent.Actions> actionsList = new ArrayList();
        if (!CollectionUtils.isEmpty(actionLogs)) {
            for(BaseLog actionLog : actionLogs) {
                RuleEngineContent.Actions action = new RuleEngineContent.Actions();
                Content actionContent = ((RuleEngineLogSerialization)this.serializationMap.get("action:" + actionLog.getType())).toContent(actionLog.getDetail());
                action.setContent(actionContent.getContent());
                action.setTime(actionContent.getTime());
                action.setType(actionLog.getType());
                actionsList.add(action);
            }
        }

        ruleEngineContent.setActions(actionsList);
        return ruleEngineContent;
    }

    @Override
    public CommonPage<RuleEngineLog> pageList(RuleEngineLogPageRequest request) {
        IPage<RuleEngineLog> page = new Page<>(request.getPageNum(), request.getPageSize());
        LambdaQueryWrapper<RuleEngineLog> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.like(StringUtils.isNotBlank(request.getRuleEngineName()), RuleEngineLog::getRuleEngineName, request.getRuleEngineName())
                .between((StringUtils.isNotBlank(request.getTimeBegin()))&&(StringUtils.isNotBlank(request.getTimeEnd())), RuleEngineLog::getTime, request.getTimeBegin(), request.getTimeEnd())
                .eq(RuleEngineLog::getTenantId, SecurityUtils.getTenantId())
                .orderByDesc(RuleEngineLog::getId);
        page = this.page(page, queryWrapper);
        return new CommonPage<>(page.getRecords(),page.getTotal(),request.getPageNum(),request.getPageSize());
    }
}
