package cn.cslg.pas.service;

import cn.cslg.pas.common.core.base.EStatus;
import cn.cslg.pas.common.utils.Response;
import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.pas.common.utils.StringUtils;
import cn.cslg.pas.domain.CustomAnalysisItem;
import cn.cslg.pas.mapper.CustomAnalysisItemMapper;
import cn.cslg.pas.common.utils.CacheUtils;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * <p>
 *  自定义分析项目 服务实现类
 * </p>
 *
 * @author 王岩
 * @since 2021-12-23
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class CustomAnalysisItemService extends ServiceImpl<CustomAnalysisItemMapper, CustomAnalysisItem> {

    private final CacheUtils cacheUtils;
    private final CustomAnalysisItemSettingService customAnalysisItemSettingService;
    private final CustomAnalysisItemSchemaService customAnalysisItemSchemaService;
    private final CustomAnalysisItemSourceService customAnalysisItemSourceService;
    private final LoginUtils loginUtils;
    public List<CustomAnalysisItem> getTreeList(Integer projectId) {
        LambdaQueryWrapper<CustomAnalysisItem> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.and(Wrapper -> Wrapper.eq(CustomAnalysisItem::getProjectId, projectId).or().eq(CustomAnalysisItem::getPermissions, 2));
        queryWrapper.orderByAsc(CustomAnalysisItem::getSort);
        List<CustomAnalysisItem> list = this.list(queryWrapper);
        list.forEach(item -> {
            item.setSetting(null);
            item.setSchema(null);
            item.setSource(null);
        });
        return this.buildTree2(list);
    }

    public CustomAnalysisItem getItemByUid(String uid) {
        CustomAnalysisItem customAnalysisItem = this.getOne(Wrappers.<CustomAnalysisItem>lambdaQuery().eq(CustomAnalysisItem::getUid, uid));
        if (customAnalysisItem.getType().equals(1)) {
            customAnalysisItem.setSetting(customAnalysisItemSettingService.getItemSettingByUid(customAnalysisItem.getUid()));
            customAnalysisItem.setSchema(customAnalysisItemSchemaService.getItemSchemaByUid(customAnalysisItem.getUid()));
            customAnalysisItem.setSource(customAnalysisItemSourceService.getItemSourceData(customAnalysisItem));
        } else {
            customAnalysisItem.setSetting(null);
            customAnalysisItem.setSchema(null);
            customAnalysisItem.setSource(null);
        }
        return customAnalysisItem;
    }

    public Integer addGroupItem(CustomAnalysisItem customAnalysisItem) {
        CustomAnalysisItem group = new CustomAnalysisItem();
        group.setUid(IdUtil.simpleUUID());
        group.setName(customAnalysisItem.getParentName());
        group.setParentId(0);
        group.setType(0);
        group.setProjectId(customAnalysisItem.getProjectId());
        group.setPermissions(2);
        group.setSort((int) this.count(Wrappers.<CustomAnalysisItem>lambdaQuery().eq(CustomAnalysisItem::getParentId, 0)) + 1);
        group.setCreateBy(loginUtils.getId());
        group.insert();
        return group.getId();
    }

    public Map<String, Object> getOptionReturnData(CustomAnalysisItem customAnalysisItem) {
        Map<String, Object> map = new HashMap<>();
        map.put("uid", customAnalysisItem.getUid());
        map.put("name", customAnalysisItem.getName());
        map.put("parentId", customAnalysisItem.getParentId());
        return map;
    }

    @Transactional(rollbackFor = Exception.class)
    public String add(CustomAnalysisItem customAnalysisItem) {
        if (this.checkNameUnique(customAnalysisItem)) {
            return Response.error("名称重复");
        }
        String uid = IdUtil.simpleUUID();
        if (StringUtils.isNotEmpty(customAnalysisItem.getParentName())) {
            customAnalysisItem.setParentId(this.addGroupItem(customAnalysisItem));
        }
        customAnalysisItem.setUid(uid);
        customAnalysisItem.setCreateBy(loginUtils.getId());
        customAnalysisItem.insert();
        if (customAnalysisItem.getType().equals(1)) {
            customAnalysisItemSettingService.add(customAnalysisItem.getSetting(), uid);
            customAnalysisItemSchemaService.add(customAnalysisItem.getSchema(), uid);
            customAnalysisItemSourceService.edit(customAnalysisItem);
        }
        return Response.success(this.getOptionReturnData(customAnalysisItem));
    }

    @Transactional(rollbackFor = Exception.class)
    public String edit(CustomAnalysisItem customAnalysisItem) {
        if (this.checkNameUnique(customAnalysisItem)) {
            return Response.error("名称重复");
        }
        CustomAnalysisItem temp = baseMapper.selectById(customAnalysisItem.getId());
        if (StringUtils.isNotEmpty(customAnalysisItem.getParentName())) {
            customAnalysisItem.setParentId(this.addGroupItem(customAnalysisItem));
        }
        temp.setName(customAnalysisItem.getName());
        temp.setParentId(customAnalysisItem.getParentId());
        temp.setSort(customAnalysisItem.getSort());
        temp.setRemark(customAnalysisItem.getRemark());
        temp.setType(customAnalysisItem.getType());
        temp.setPermissions(customAnalysisItem.getPermissions());
        temp.setSchema(customAnalysisItem.getSchema());
        temp.setSetting(customAnalysisItem.getSetting());
        temp.setSource(customAnalysisItem.getSource());
        temp.setProjectId(customAnalysisItem.getProjectId());
        temp.updateById();
        if (temp.getType().equals(1)) {
            customAnalysisItemSettingService.edit(temp.getSetting(), temp.getUid());
            customAnalysisItemSchemaService.edit(temp.getSchema(), temp.getUid());
            customAnalysisItemSourceService.edit(temp);
        }
        return Response.success(this.getOptionReturnData(temp));
    }

    @Transactional
    public String delete(Integer id) {
        CustomAnalysisItem customAnalysisItem = baseMapper.selectById(id);
        if (this.list(Wrappers.<CustomAnalysisItem>lambdaQuery().eq(CustomAnalysisItem::getParentId, id)).size() != 0) {
            return Response.error("删除失败，请先删除子节点");
        }
        this.removeById(id);
        customAnalysisItemSchemaService.deleteByUid(customAnalysisItem.getUid());
        customAnalysisItemSettingService.deleteByUid(customAnalysisItem.getUid());
        customAnalysisItemSourceService.deleteByUid(customAnalysisItem.getUid());
        return Response.success(true);
    }

    public List<CustomAnalysisItem> buildTree2(List<CustomAnalysisItem> items) {
        List<CustomAnalysisItem> returnList = items.stream().filter(item -> item.getParentId().equals(0)).collect(Collectors.toList());
        returnList.forEach(item -> {
            item.setChildren(items.stream().filter(c -> c.getParentId().equals(item.getId())).collect(Collectors.toList()));
        });
        return returnList;
    }

    public List<CustomAnalysisItem> buildTree(List<CustomAnalysisItem> items) {
        List<CustomAnalysisItem> returnList = new ArrayList<>();
        List<Integer> tempList = new ArrayList<>();
        for (CustomAnalysisItem option : items) {
            tempList.add(option.getId());
        }
        for (Iterator<CustomAnalysisItem> iterator = items.iterator(); iterator.hasNext(); ) {
            CustomAnalysisItem item = (CustomAnalysisItem) iterator.next();
            if (!tempList.contains(item.getParentId())) {
                recursionFn(items, item);
                returnList.add(item);
            }
        }
        if (returnList.isEmpty()) {
            returnList = items;
        }
        return returnList;
    }

    private void recursionFn(List<CustomAnalysisItem> list, CustomAnalysisItem t) {
        List<CustomAnalysisItem> childList = getChildList(list, t);
        t.setChildren(childList);
        for (CustomAnalysisItem tChild : childList) {
            if (hasChild(list, tChild)) {
                recursionFn(list, tChild);
            }
        }
    }

    private List<CustomAnalysisItem> getChildList(List<CustomAnalysisItem> list, CustomAnalysisItem t) {
        List<CustomAnalysisItem> tlist = new ArrayList<>();
        Iterator<CustomAnalysisItem> it = list.iterator();
        while (it.hasNext()) {
            CustomAnalysisItem n = (CustomAnalysisItem) it.next();
            if (n.getParentId().equals(t.getId())) {
                tlist.add(n);
            }
        }
        return tlist;
    }

    private boolean hasChild(List<CustomAnalysisItem> list, CustomAnalysisItem t) {
        return getChildList(list, t).size() > 0 ? true : false;
    }

    public Boolean checkNameUnique(CustomAnalysisItem customAnalysisItem) {
        Integer id = StringUtils.isNull(customAnalysisItem.getId()) ? -1 : customAnalysisItem.getId();
        CustomAnalysisItem info = this.getOne(Wrappers.<CustomAnalysisItem>lambdaQuery().eq(CustomAnalysisItem::getParentId, customAnalysisItem.getParentId()).eq(CustomAnalysisItem::getName, customAnalysisItem.getName()).eq(CustomAnalysisItem::getType, customAnalysisItem.getType()).last("limit 1"));
        return StringUtils.isNotNull(info) && !info.getId().equals(id);
    }
}
