package cn.cslg.report.service.business.InvalidReReport;

import cn.cslg.report.common.model.dto.invalidReReport.ProofGroupDTO;
import cn.cslg.report.common.model.dto.invalidReReport.ProofGroupUpdateDTO;
import cn.cslg.report.common.model.vo.PersonnelVO;
import cn.cslg.report.common.model.vo.invalidReReport.ProofGroupDetailVO;
import cn.cslg.report.common.model.vo.invalidReReport.ProofGroupVO;
import cn.cslg.report.common.utils.CacheUtils;
import cn.cslg.report.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.report.entity.CompareFiles;
import cn.cslg.report.entity.Features;
import cn.cslg.report.entity.invalidReReport.*;
import cn.cslg.report.exception.XiaoShiException;
import cn.cslg.report.mapper.InvalidReReport.ProofGroupMapper;
import cn.cslg.report.service.business.CompareFilesService;
import cn.cslg.report.service.business.FeatureService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;


@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ProofGroupService extends ServiceImpl<ProofGroupMapper, ProofGroup> {
    private final CacheUtils cacheUtils;
    private final LoginUtils loginUtils;
    private final AssoProofGroupService assoProofGroupService;
    private final ProofGroupService proofGroupService;
    private final CompareFilesService compareFilesService;
    private final ArgumentsService argumentsService;
    private final FeatureService featureService;
    private final ProofStrService assoFeatureProofService;
    private final AssoProofGroupStrService assoProofGroupStrService;

    /**
     * 批量添加证据组合
     *
     * @param proofGroupDTOS
     */
    public void addProofGroup(List<ProofGroupDTO> proofGroupDTOS) {
        for (ProofGroupDTO proofGroupDTO : proofGroupDTOS) {
            //判断proofIds是否为空，若为空则返回
            if (proofGroupDTO.getGroupDetails() != null && proofGroupDTO.getGroupDetails().size() != 0) {
                //添加证据组合
                ProofGroup proofGroup = new ProofGroup();
                BeanUtils.copyProperties(proofGroupDTO, proofGroup);
                //获取当前登录人信息
                PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
                proofGroup.setCreateId(personnelVO.getId());
                //            proofGroup.setCreateId(1);
                proofGroup.insert();
                //添加证据组合和证据关联
                //批量插入组合和专利关联表
                List<AssoProofGroup> assoProofGroups = new ArrayList<>();
                //批量查出组合和无效证据关联表
                List<AssoProofGroupStr> assoProofGroupStrs = new ArrayList<>();
                for (int i = 0; i < proofGroupDTO.getGroupDetails().size(); i++) {
                    Integer compareFileId = proofGroupDTO.getGroupDetails().get(i).getCompareFileId();
                    AssoProofGroup assoProofGroup = new AssoProofGroup();
                    assoProofGroup.setGroupId(proofGroup.getId());
                    assoProofGroup.setProofId(compareFileId);
                    assoProofGroup.setCreateId(personnelVO.getId());
                    assoProofGroups.add(assoProofGroup);
                    List<Integer> proofStrIds = proofGroupDTO.getGroupDetails().get(i).getProofStrIds();
                    proofStrIds.forEach(item -> {
                        AssoProofGroupStr assoProofGroupStr = new AssoProofGroupStr();
                        assoProofGroupStr.setProofGroupId(proofGroup.getId());
                        assoProofGroupStr.setProofStrId(item);
                        assoProofGroupStr.setCompareFileId(compareFileId);
                        assoProofGroupStrs.add(assoProofGroupStr);
                    });
                }
                assoProofGroupService.saveBatch(assoProofGroups);
                assoProofGroupStrService.saveBatch(assoProofGroupStrs);
            } else {
                throw new XiaoShiException("传入数据不能为空");
            }
        }
    }


    /**
     * 批量删除证据组合
     *
     * @param ids 证据组合ids
     * @return
     */
    public void deleteProofGroup(List<Integer> ids) {
        if (ids != null && ids.size() != 0) {
            //根据证据组合id批量删除证据组合-证据关联
            LambdaQueryWrapper<AssoProofGroup> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(AssoProofGroup::getGroupId, ids);
            assoProofGroupService.remove(queryWrapper);
            //根据ids批量删除证据组合
            this.removeByIds(ids);
        } else {
            throw new XiaoShiException("删除错误");
        }
    }

    /**
     * 批量删除证据组合
     *
     * @param
     * @return
     */
    public void deleteProofGroupByInvalid(Integer invalidId) {
        //根据无效理由id获得证据组合
        LambdaQueryWrapper<ProofGroup> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ProofGroup::getInvalidReasonId, invalidId);
        List<ProofGroup> proofGroups = this.list(wrapper);
        List<Integer> ids = proofGroups.stream().map(ProofGroup::getId).collect(Collectors.toList());
        ;
        if (ids != null && ids.size() != 0) {
            //根据证据组合id批量删除证据组合-证据关联
            LambdaQueryWrapper<AssoProofGroup> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(AssoProofGroup::getGroupId, ids);
            assoProofGroupService.remove(queryWrapper);
            //根据ids批量删除证据组合
            this.removeByIds(ids);
            //根据证据组合id批量删除证据组合-无效证据关联
            LambdaQueryWrapper<AssoProofGroupStr> strWrapper = new LambdaQueryWrapper<>();
            strWrapper.in(AssoProofGroupStr::getProofGroupId, ids);
            assoProofGroupStrService.remove(strWrapper);
            //根据ids批量删除证据组合
            this.removeByIds(ids);
        }

    }

    /**
     * 更新证据组合
     *
     * @param proofGroupUpdateDTO
     * @return
     */
    public void updateProofGroup(ProofGroupUpdateDTO proofGroupUpdateDTO) {
             List<Integer> newProofIds = proofGroupUpdateDTO.getProofStrIds();
            //查出证据组合数据
            ProofGroup proofGroup = this.getById(proofGroupUpdateDTO.getId());
            proofGroup.setArgumentStr(proofGroupUpdateDTO.getArgumentStr());
            proofGroup.setDescription(proofGroupUpdateDTO.getDescription());
            proofGroup.updateById();
            //证据组合id
            Integer groupId = proofGroup.getId();
            Integer compareFileId =proofGroupUpdateDTO.getCompareFileId();
            //根据证据组合id查找 证据组合和证据关联ids
            if(compareFileId!=null) {
                LambdaQueryWrapper<AssoProofGroupStr> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(AssoProofGroupStr::getProofGroupId, groupId)
                        .eq(AssoProofGroupStr::getCompareFileId, compareFileId);
                List<AssoProofGroupStr> assoProofGroupStrs = assoProofGroupStrService.list(queryWrapper);
                List<Integer> oldProofStrIds = assoProofGroupStrs.stream().map(AssoProofGroupStr::getId).collect(Collectors.toList());
                if (oldProofStrIds.size() > 0) {
                    assoProofGroupStrService.removeByIds(oldProofStrIds);
                }
                //寻找proofIds比关联ids多的id并插入到证据组合和证据关联表中
                //批量插入
                List<AssoProofGroupStr> needInsert = new ArrayList<>();
                for (int i = 0; i < newProofIds.size(); i++) {
                    AssoProofGroupStr assoProofGroupStr = new AssoProofGroupStr();
                    assoProofGroupStr.setProofGroupId(groupId);
                    assoProofGroupStr.setProofStrId(newProofIds.get(i));
                    assoProofGroupStr.setCompareFileId(proofGroupUpdateDTO.getCompareFileId());
                    needInsert.add(assoProofGroupStr);
                }
                assoProofGroupStrService.saveBatch(needInsert);
            }

    }

    /**
     * 查询证据组合详情
     *
     * @param id 证据组合id
     * @return
     */
    public ProofGroupVO queryProofGroupDetail(Integer id) {
        //根据证据组合id查询证据组合并装载到ProofGroupVO类里
        ProofGroupVO proofGroupVO = new ProofGroupVO();
        ProofGroup proofGroup = this.getById(id);
        if (proofGroup == null) {
            throw new XiaoShiException("没有这一条数据");
        }
        proofGroupVO.setInvalidReasonId(proofGroup.getInvalidReasonId());
        proofGroupVO.setArgument_str(proofGroup.getArgumentStr());
        proofGroupVO.setDescription(proofGroup.getDescription());
        LambdaQueryWrapper<AssoProofGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AssoProofGroup::getProofId);
        queryWrapper.eq(AssoProofGroup::getGroupId, id);
        List<AssoProofGroup> AssoProofGroups = assoProofGroupService.list(queryWrapper);
        List<Integer> proofIds = AssoProofGroups.stream().map(AssoProofGroup::getProofId).collect(Collectors.toList());
        proofGroupVO.setProofIds(proofIds);
        return proofGroupVO;
    }

    /**
     * 查询证据组合
     *
     * @param invalidId 无效理由Id
     * @return proofGroups
     */
    public List<ProofGroup> queryProofGroup(Integer invalidId) {
        //根据无效理由Id查询证据组合列表，并返回
        LambdaQueryWrapper<ProofGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProofGroup::getInvalidReasonId, invalidId);
        List<ProofGroup> proofGroups = this.list(queryWrapper);
        return proofGroups;
    }


    /**
     * 根据无效理由id查询证据组合及证据详情
     *
     * @param invalidReasonId 无效理由id
     * @return
     */
    public List<ProofGroupDetailVO> queryDetailByInvalidId(Integer invalidReasonId) {
        List<ProofGroupDetailVO> proofDetailVOS = new ArrayList<>();
        //根据无效理由和证据id查询证据组合
        LambdaQueryWrapper<ProofGroup> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(ProofGroup::getInvalidReasonId, invalidReasonId);
        List<ProofGroup> proofGroups = proofGroupService.list(lambdaQueryWrapper);
        if (proofGroups.size() == 0) {
            return new ArrayList<>();
        }
        //根据证据组合id查询证据id
        List<Integer> groupIds = proofGroups.stream().map(ProofGroup::getId).collect(Collectors.toList());
        LambdaQueryWrapper<AssoProofGroup> assoWrapper = new LambdaQueryWrapper<>();
        assoWrapper.in(AssoProofGroup::getGroupId, groupIds);
        List<AssoProofGroup> assoProofGroups = assoProofGroupService.list(assoWrapper);
        List<Integer> proofIds = assoProofGroups.stream().map(AssoProofGroup::getProofId).collect(Collectors.toList());
        //根据证据id查询证据
        LambdaQueryWrapper<CompareFiles> comFileWrapper = new LambdaQueryWrapper<>();
        comFileWrapper.in(CompareFiles::getId, proofIds);
        List<CompareFiles> compareFiles = compareFilesService.list(comFileWrapper);
        //根据证据id查询陈述意见
        List<Arguments> arguments = new ArrayList<>();
        LambdaQueryWrapper<Arguments> argumentsWrapper = new LambdaQueryWrapper<>();
        argumentsWrapper.in(Arguments::getProofId, proofIds);
        arguments = argumentsService.list(argumentsWrapper);
        //根据特征id获得特征列表
        List<Features> features = new ArrayList<>();
        List<Integer> featureIds = arguments.stream().map(Arguments::getFeatureId).collect(Collectors.toList());
        if (featureIds.size() != 0) {
            LambdaQueryWrapper<Features> featuresWrapper = new LambdaQueryWrapper<>();
            featuresWrapper.in(Features::getId, featureIds);
            features = featureService.list(featuresWrapper);
        }
        //根据证据组合id查找组合和无效证据关联
        LambdaQueryWrapper<AssoProofGroupStr> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(AssoProofGroupStr::getProofGroupId, groupIds);
        List<AssoProofGroupStr> assoProofGroupStrs = assoProofGroupStrService.list(wrapper);
        //根据特征id获得无效证据
        List<ProofStr> proofStrs = new ArrayList<>();
        if (featureIds.size() != 0) {
            LambdaQueryWrapper<ProofStr> assoFPWrapper = new LambdaQueryWrapper<>();
            assoFPWrapper.in(ProofStr::getFeatureId, featureIds);
            proofStrs = assoFeatureProofService.list(assoFPWrapper);
        }
        //装载列表
        for (ProofGroup proofGroup : proofGroups) {
            ProofGroupDetailVO proofGroupDetailVO = new ProofGroupDetailVO();
            proofGroupDetailVO.setId(proofGroup.getId());
            proofGroupDetailVO.setInvalidReasonId(proofGroup.getInvalidReasonId());
            proofGroupDetailVO.setArgumentStr(proofGroup.getArgumentStr());
            proofGroupDetailVO.setDescription(proofGroup.getDescription());
            List<ProofGroupDetailVO.ProofIn> proofIns = new ArrayList<>();
            //根据组合id获得该组合下的证据
            List<AssoProofGroup> assoProofGroupPart = assoProofGroups.stream().filter(item -> item.getGroupId().equals(proofGroup.getId())).collect(Collectors.toList());
            List<Integer> proofIdsPart = assoProofGroupPart.stream().map(AssoProofGroup::getProofId).collect(Collectors.toList());
            List<CompareFiles> compareFilesPart = compareFiles.stream().filter(item -> proofIdsPart.contains(item.getId())).collect(Collectors.toList());
            //装载证据信息
            for (CompareFiles compareFile : compareFilesPart) {
                ProofGroupDetailVO.ProofIn proofIn = new ProofGroupDetailVO.ProofIn();
                proofIn.setId(compareFile.getId());
                proofIn.setFileId(compareFile.getFileId());
                proofIn.setSort(compareFile.getSysOrder());
                proofIn.setFileType(compareFile.getFileType());
                proofIn.setPatentNo(compareFile.getPatentNo());
                proofIns.add(proofIn);
            }
           //获得证据组合里的无效证据
            List<Integer> proofStrIdsPart =assoProofGroupStrs.stream().filter(item->item.getProofGroupId().equals(proofGroup.getId())).map(AssoProofGroupStr::getProofStrId).collect(Collectors.toList());
            List<ProofStr> proofStrsPart =proofStrs.stream().filter(item->proofStrIdsPart.contains(item.getId())).collect(Collectors.toList());
           //遍历无效证据
            List<ProofGroupDetailVO.ProofDetailIn> proofDetailIns = new ArrayList<>();
            for (ProofStr proofStr : proofStrsPart) {
                CompareFiles tenCom=   compareFilesPart.stream().filter(item->proofStr.getCompareFileId().equals(item.getId())).findFirst().orElse(new CompareFiles());
                ProofGroupDetailVO.ProofDetailIn proofDetailIn =new ProofGroupDetailVO.ProofDetailIn();
                //获得对应特征信息
                Features features1 =features.stream().filter(item->item.getId().equals(proofStr.getFeatureId())).findFirst().orElse(new Features());
                //装载无效证据
                proofDetailIn.setProofStrId(proofStr.getId());
                proofDetailIn.setProofStr(proofStr.getProofStr());
                proofDetailIn.setProofId(proofStr.getCompareFileId());
                proofDetailIn.setSort(tenCom.getSysOrder());
                proofDetailIn.setFeaturesOrder(features1.getFeaturesOrder());
                proofDetailIn.setFeatureContent(features1.getContent());
                proofDetailIn.setFeatureId(features1.getId());
            List<Arguments> argumentsParts =arguments.stream().filter(item->proofStr.getId().equals(item.getProofStrId())).collect(Collectors.toList());
            List<ProofGroupDetailVO.ArgumentIn> argumentIns = new ArrayList<>();
           //遍历陈述意见
            for(Arguments arguments1: argumentsParts){
                ProofGroupDetailVO.ArgumentIn argumentIn =new ProofGroupDetailVO.ArgumentIn();
                argumentIn.setId(arguments1.getId());
                argumentIn.setArgumentStr(arguments1.getArgumentStr());
                argumentIns.add(argumentIn);
            }
                proofDetailIn.setArguments(argumentIns);
                proofDetailIns.add(proofDetailIn);
            }
            proofIns.sort(Comparator.comparing(ProofGroupDetailVO.ProofIn::getSort));
            proofGroupDetailVO.setProofs(proofIns);
            proofDetailIns.sort(Comparator.comparing(ProofGroupDetailVO.ProofDetailIn::getFeaturesOrder));
            proofGroupDetailVO.setProofDetails(proofDetailIns);
            proofDetailVOS.add(proofGroupDetailVO);
        }
        return proofDetailVOS;
    }

}