package com.ruoyi.sim.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.sim.domain.TaskFault;
import com.ruoyi.sim.domain.vo.FaultTreeVo;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.sim.mapper.FaultMapper;
import com.ruoyi.sim.domain.Fault;

/**
 * 故障Service业务层处理
 *
 * @author tom
 * @date 2024-12-15
 */
@Service
public class FaultService {
    @Autowired
    private FaultMapper faultMapper;

    /**
     * 查询故障
     *
     * @param faultId 故障主键
     * @return 故障
     */
    public Fault selectFaultByFaultId(String faultId) {
        return faultMapper.selectFaultByFaultId(faultId);
    }

    /**
     * 查询故障列表
     *
     * @param fault 故障
     * @return 故障
     */
    public List<Fault> selectFaultList(Fault fault) {
        return faultMapper.selectFaultList(fault);
    }

    /**
     * 新增故障
     *
     * @param fault 故障
     * @return 结果
     */
    public int insertFault(Fault fault) {
        fault.setCreateTime(DateUtils.getNowDate());
        return faultMapper.insertFault(fault);
    }

    /**
     * 修改故障
     *
     * @param fault 故障
     * @return 结果
     */
    public int updateFault(Fault fault) {
        fault.setUpdateTime(DateUtils.getNowDate());
        return faultMapper.updateFault(fault);
    }

    /**
     * 批量删除故障
     *
     * @param faultIds 需要删除的故障主键
     * @return 结果
     */
    public int deleteFaultByFaultIds(String[] faultIds) {
        return faultMapper.deleteFaultByFaultIds(faultIds);
    }

    /**
     * 删除故障信息
     *
     * @param faultId 故障主键
     * @return 结果
     */
    public int deleteFaultByFaultId(String faultId) {
        return faultMapper.deleteFaultByFaultId(faultId);
    }

    // -------------------------------- tom add  --------------------------------
    private static final Logger l = LoggerFactory.getLogger(FaultService.class);
    @Autowired
    private SimService simService;

    public boolean isEnable(String faultId) {
        Fault q = new Fault();
        q.setFaultId(faultId);
        Fault f = selectFaultByFaultId(faultId);
        if (f == null) {
            return false;
        }
        return (Fault.State.ENABLE.equals(f.getFaultState()));
    }

    public boolean isDisable(String faultId) {
        return !isEnable(faultId);
    }

    public List<Fault> listAllEnable(final String simType) {
        Fault q = new Fault();
        q.setSimType(simType);
        q.setFaultState(Fault.State.ENABLE);
        return selectFaultList(q);
    }

    public List<Fault> listAllType3EnableBySimType(final String simType) {
        Fault q = new Fault();
        q.setSimType(simType);
        q.setFaultType(Fault.TYPE_3);
        q.setFaultState(Fault.State.ENABLE);
        return selectFaultList(q);
    }

    public List<Fault> listAllType3And4EnableBySimType(final String simType) {
        List<Fault> list = new ArrayList<>();
        listAllEnable(simType)
                .stream()
                .filter(Objects::nonNull)
                .filter(f -> (Fault.TYPE_1.equals(f.getFaultType()) || Fault.TYPE_3.equals(f.getFaultType())))
                .forEach(list::add);
        return list;
    }

    /**
     * 查询故障列表tree
     *
     * @return 故障
     */
    public AjaxResult listAllTreeStyleBySimType(final String simType) {
        // check
        if (StringUtils.isEmpty(simType)) {
            return AjaxResult.error("simType empty!");
        }
        if (!simService.checkSimTypeOk(simType)) {
            return AjaxResult.error("simType value error!");
        }
        List<Fault> list = listAllType3And4EnableBySimType(simType);
        // 按照faultId升序排序
        Collections.sort(list);
        List<FaultTreeVo> tempListNode = new ArrayList<>();
        for (Fault s : list) {
            FaultTreeVo t = new FaultTreeVo();
            BeanUtils.copyProperties(s, t);
            tempListNode.add(t);
        }
        l.info(Objects.requireNonNull(tempListNode).toString());
        List<FaultTreeVo> tree = toTree(tempListNode, Fault.ROOT_FAULT_ID);
        l.info(Objects.requireNonNull(tree).toString());
        return AjaxResult.success(tree);
    }


//    private static List<FaultNode> toTree2(List<FaultNode> list) {
//        List<FaultNode> tree = new ArrayList<>();
//        for (FaultNode fn1 : list) {
//            if (fn1.getParentFaultId().equals(ROOT_FAULT_ID)) {
//                tree.add(fn1);
//            }
//            for (FaultNode fn2 : list) {
//                if (fn2.getParentFaultId().equals(fn1.getParentFaultId())) {
//                    if (fn1.getChildren() == null) {
//                        fn1.setChildren(new ArrayList<>());
//                    }
//                    fn1.getChildren().add(fn2);
//                }
//            }
//        }
//        return tree;
//    }

    public static List<FaultTreeVo> toTree(List<FaultTreeVo> list, String parentFaultId) {
        // todo:sort
        List<FaultTreeVo> tree = list
                .stream()
                .filter(
                        parent ->
                                parent.getParentFaultId().equals(parentFaultId))
                .map(child -> {
                    if (child.getTaskFault() == null) {
                        child.setTaskFault(new TaskFault(0L, 0L, child.getFaultId(), TaskFault.UNKNOWN));
                    }
                    child.setChildren(toTree(list, child.getFaultId()));
                    return child;
                })
                .collect(Collectors.toList());
        return tree;
    }

    public static List<FaultTreeVo> flatten(List<FaultTreeVo> list) {
        return list
                // todo:stream filter

//                .stream()
//                .filter(x -> {
//                    return StringUtils.isEmpty(x.getParentFaultId());
//                })
//                .collect(Collectors.toList())
                .stream()
                .map(x -> {
                    return flatten(x, list);
                })
                .flatMap(Collection::stream)
                .distinct()
                .collect(Collectors.toList());
    }

    public static List<FaultTreeVo> flatten(FaultTreeVo node, List<FaultTreeVo> list2222) {
        List<FaultTreeVo> results = new ArrayList<>();
        if (node != null) {
            // get rid of children & parent references
            FaultTreeVo target = new FaultTreeVo();
            BeanUtils.copyProperties(node, target);
            results.add(target);
        }

        List<FaultTreeVo> children = node.getChildren();
        for (FaultTreeVo child : children) {
            if (child.getChildren() != null) {
                // Recursive call - Keep flattening until no more children
                List<FaultTreeVo> flatten = flatten(child, list2222);
                results.addAll(flatten);
            }
        }
        // stop or exit condition
        return results;
    }
}
