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

import cn.cslg.report.common.model.dto.invalidReReport.*;
import cn.cslg.report.common.model.vo.PersonnelVO;
import cn.cslg.report.common.model.vo.invalidReReport.*;
import cn.cslg.report.common.utils.CacheUtils;
import cn.cslg.report.common.utils.DataUtils;
import cn.cslg.report.common.utils.Response;
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.Report;
import cn.cslg.report.entity.invalidReReport.*;
import cn.cslg.report.mapper.FeatureMapper;
import cn.cslg.report.mapper.InvalidReReport.InvalidReasonMapper;
import cn.cslg.report.service.business.CompareFilesService;
import cn.cslg.report.service.business.FeatureService;
import cn.cslg.report.service.business.ReportService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.omg.CORBA.DynAnyPackage.Invalid;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;

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


@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class InvalidReasonService extends ServiceImpl<InvalidReasonMapper, InvalidReason> {
    private final ReportService reportService;
    private final AssoPositionFeaturesService assoPositionFeaturesService;
    private final AssoProofGroupService assoProofGroupService;
    private final FeatureService featureService;
    private final FeatureMapper featureMapper;
    private final ProofGroupService proofGroupService;
    private final CacheUtils cacheUtils;
    private final LoginUtils loginUtils;
    private final CompareFilesService compareFilesService;
    private final InvalidReasonFieldValueService invalidReasonFieldValueService;

    /**
     * 判断特征是否有重复的方法
     *
     * @param checkReFeaturesDTO
     */
    public Boolean checkReFeatures(CheckReFeaturesDTO checkReFeaturesDTO) {
        //查出表中制定报告和权要的全部特征内容和位置
        List<QueryAllFeaturesVO> queryAllFeaturesVOS = featureMapper.queryAllFeatures(checkReFeaturesDTO.getReportId(), checkReFeaturesDTO.getRightSort());
        //List<QueryAllFeaturesVO> list = queryAllFeaturesVOS.stream().sorted(Comparator.comparing(QueryAllFeaturesVO::getPosition)).collect(Collectors.toList());
        //取出需要插入的特征内容和位置
        List<CheckReFeaturesDTO.featuresIn> features = checkReFeaturesDTO.getFeatures();
        //定义一个map装载所有的特征内容和位置
        Map<Integer, Integer> map = new HashMap<>();
        //遍历装载查询出来的全部特征内容和位置
        for (QueryAllFeaturesVO queryAllFeaturesVO : queryAllFeaturesVOS) {
            //位置
            Integer position = queryAllFeaturesVO.getPosition();
            //特征内容字符串的长度
            Integer length = queryAllFeaturesVO.getFeatureStr().length();
            if (position != null && length > 0) {
                //如果map中已经有了初始位置，无论长度如何都重复
                if (map.containsKey(position)) {
                    return false;
                } else {
                    map.put(position, length);
                }
            } else {
                return false;
            }
        }
        //遍历装载需要插入的特征内容和位置
        for (CheckReFeaturesDTO.featuresIn featuresIn : features) {
            //如果map中已经有了初始位置，无论长度如何都重复
            if (map.containsKey(featuresIn.getPosition())) {
                return false;
            } else {
                map.put(featuresIn.getPosition(), featuresIn.getFeatureStr().length());
            }
        }
        //set中没有重复元素
        Set<Integer> keySet = map.keySet();
        //获取到所有的初始位置,并排序
        List<Integer> positions = new ArrayList<>(keySet);
        Collections.sort(positions);
        //遍历需要插入的特征内容和位置
        for (CheckReFeaturesDTO.featuresIn featuresIn : features) {
            //需检查是否重复的特征内容的初始位置 在集合中的位置
            Integer index = positions.indexOf(featuresIn.getPosition());
            //需检查是否重复的特征内容的末尾位置
            Integer endPosition = featuresIn.getPosition() + featuresIn.getFeatureStr().length();
            //前面一个特征内容的初始位置
            Integer preFeaInitialPos = index > 0 ? positions.get(index - 1) : -1;
            //前面一个特征内容的长度
            Integer preLength = index > 0 ? map.get(preFeaInitialPos) : -1;
            //前面一个特征的末尾位置
            Integer preEndPosition = preFeaInitialPos + preLength - 1;
            //后面一个特征内容的初始位置
            Integer nextFeaInitialPos = index < positions.size() - 1 ? positions.get(index + 1) : -1;
            //判断是否与前面一个特征内容重复（前面一个特征内容的末尾位置如果比插入的特征内容的初始位置大，则重复了）
            if (index > 0 && preEndPosition > featuresIn.getPosition()) {
                return false;
            } else if (index < (positions.size() - 1) && endPosition > nextFeaInitialPos) {//判断是否与后面一个特征内容重复（如果插入的特征内容的末尾位置，比后面一个特征内容的初始位置大，则重复）
                return false;
            }
        }
        return true;
    }

    /**
     * 添加无效理由和证据
     *
     * @param invalidReasonDTO 无效理由和证据Dto类
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String addInvalidReason(InvalidReasonDTO invalidReasonDTO) {
        InvalidReason invalidReason = new InvalidReason();
        //判断invalidName的类型
        Integer invalidName = invalidReasonDTO.getInvalidName();
        if (invalidName.equals(1)) {//若类型为1，则为说明书公开不充分,涉及内容为说明书，手动输入无效证据
            BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
            //获取当前登陆人信息
            PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
            invalidReason.setCreateId(personnelVO.getId());
            //说明书公开不充分入表
            invalidReason.insert();
        } else if (invalidName.equals(0)) {//若类型为0，则为“权利要求不清楚”，需要选择涉及内容（content）并输入相关证据（proofStr）
            if (invalidReasonDTO.getProofStr() != null && invalidReasonDTO.getProofStr() != "") {
                if (invalidReasonDTO.getInvalidName() == 1) {
                    invalidReasonDTO.setContent(-1);
                }
                //复制DTO类字段到InvalidReason实体类并保存入库
                BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
                //获取当前登陆人信息
                PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
                invalidReason.setCreateId(personnelVO.getId());
                //权要排序字段 值为content
                invalidReason.setRightSort(invalidReasonDTO.getContent());
                //无效理由入表
                invalidReason.insert();
                //有可能为特征不清楚
                //判断是否传入特征集合
                if (invalidReasonDTO.getFeatures() != null && invalidReasonDTO.getFeatures().size() > 0) {
                    //若类型为0检查features是否有交集（根据位置和字符串长度判断）若有则返回
                    Features features = new Features();
                    //特征内容
                    List<InvalidReasonDTO.FeaturesIn> featuresIns = invalidReasonDTO.getFeatures();
                    //检查特征内容是否有交集（根据位置和字符串长度判断）若有则返回
                    //装载检查重复需要的类
                    CheckReFeaturesDTO checkReFeaturesDTO = new CheckReFeaturesDTO();
                    checkReFeaturesDTO.setReportId(invalidReasonDTO.getReportId());
                    checkReFeaturesDTO.setRightSort(invalidReasonDTO.getContent());
                    List<CheckReFeaturesDTO.featuresIn> checkFeatureIns = new ArrayList<>();
                    for (InvalidReasonDTO.FeaturesIn featuresIn : featuresIns) {
                        CheckReFeaturesDTO.featuresIn featuresIn1 = new CheckReFeaturesDTO.featuresIn();
                        BeanUtils.copyProperties(featuresIn, featuresIn1);
                        checkFeatureIns.add(featuresIn1);
                    }
                    checkReFeaturesDTO.setFeatures(checkFeatureIns);
                    Boolean isFlag = this.checkReFeatures(checkReFeaturesDTO);
                    if (isFlag == false) {
                        return Response.error("特征内容重复");
                    }
                    //不重复则需要入表
                    //标的专利号,权要id,特征内容,报告id
                    //通过报告id查询标的专利号
                    Integer reportId = invalidReasonDTO.getReportId();
                    LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.select(Report::getSignPatentNo);
                    queryWrapper.eq(Report::getId, reportId);
                    Report report = reportService.getOne(queryWrapper);
                    features.setSignPatentNo(report.getSignPatentNo());
                    //权要id（DTO类的content字段）
                    features.setRightId(invalidReasonDTO.getContent());
                    //报告id
                    features.setReportId(reportId);
                    //遍历特征内容集合，保存到表（类型为0）
                    for (int i = 0; i < featuresIns.size(); i++) {
                        //若类型为0,保存到特征表
                        InvalidReasonDTO.FeaturesIn featuresIn = featuresIns.get(i);
                        features.setContent(featuresIn.getFeatureStr());
                        features.insert();
                        //若类型为0,保存到特征与位置关联表(特征id,位置)
                        AssoPositionFeatures assoPositionFeatures = new AssoPositionFeatures();
                        assoPositionFeatures.setFeaturesID(features.getId());
                        assoPositionFeatures.setPosition(featuresIn.getPosition());
                        assoPositionFeatures.insert();
                    }
                }
            } else {
                return Response.error("相关证据不能为空");
            }
        } else if (invalidName.equals(2) || invalidName.equals(3)) {//若类型为2,3则proofGroups不能为空
            if (invalidReasonDTO.getProofGroups() != null) {
                //复制DTO类字段到InvalidReason实体类并保存入库
                BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
                //获取当前登陆人信息
                PersonnelVO personnelVO = cacheUtils.getLoginUser(loginUtils.getId());
                invalidReason.setCreateId(personnelVO.getId());
                invalidReason.insert();
                //根据proofGroups保存proofGroup
                List<ProofGroupDTO> proofGroupDTOS = new ArrayList<>();
                for (InvalidReasonDTO.ProofGroupIn proofGroupIn : invalidReasonDTO.getProofGroups()) {
                    ProofGroupDTO proofGroupDTO = new ProofGroupDTO();
                    proofGroupDTO.setInvalidReasonId(invalidReason.getId());//无效理由id
                    proofGroupDTO.setDescription(proofGroupIn.getDescription());//描述
                    proofGroupDTO.setArgumentStr(proofGroupIn.getArgumentStr());//陈述意见
                    proofGroupDTO.setGroupDetails(proofGroupIn.getGroupDetails());//证据ids
                    proofGroupDTOS.add(proofGroupDTO);
                }
                proofGroupService.addProofGroup(proofGroupDTOS);
            } else {
                return Response.error("证据组合不能为空");
            }
        }
        //添加自定义字段值
        if (invalidReasonDTO.getFields() != null) {
            invalidReasonDTO.getFields().forEach(item -> {
                item.setInvalidReasonId(invalidReason.getId());
            });
        }
        invalidReasonFieldValueService.addOrUpdate(invalidReasonDTO.getFields());
        return Response.success("添加成功");
    }

    /**
     * 删除无效理由
     *
     * @param ids 无效理由id
     * @return
     * @throws IOException
     */
    @Transactional(rollbackFor = Exception.class)
    public String deleteInvalidReason(List<Integer> ids) {
        //根据ids删除proofGroup表内容
        LambdaQueryWrapper<ProofGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(ProofGroup::getId);
        queryWrapper.in(ProofGroup::getInvalidReasonId, ids);
        proofGroupService.remove(queryWrapper);
        //根据ids删除InvalidReason内容
        this.removeByIds(ids);
        return Response.success("删除成功");
    }

    /**
     * 更新无效理由和证据
     *
     * @param invalidReasonDTO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String updateInvalidReason(InvalidReasonDTO invalidReasonDTO) {
        if (invalidReasonDTO.getId() == null) {
            return Response.error("请选择无效理由");
        }
        Integer invalidName = invalidReasonDTO.getInvalidName();
        InvalidReason invalidReason = this.getById(invalidReasonDTO.getId());
        if (invalidName.equals(1)) {//若类型为1，则为说明书公开不充分,涉及内容为说明书，手动输入无效证据
            BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
            //说明书公开不充分入表
            invalidReason.updateById();
        } else if (invalidName.equals(0)) {//若类型为0，则为“权利要求不清楚”，需要选择涉及内容（content）并输入相关证据（proofStr）
            if (invalidReasonDTO.getProofStr() != null && invalidReasonDTO.getProofStr() != "") {
                if (invalidReasonDTO.getInvalidName() == 1) {
                    invalidReasonDTO.setContent(-1);
                }
                //复制DTO类字段到InvalidReason实体类并保存入库
                BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
                //权要排序字段 值为content
                invalidReason.setRightSort(invalidReasonDTO.getContent());
                //无效理由入表
                invalidReason.updateById();
                //有可能为特征不清楚
                //判断是否传入特征集合 (更新无特征更新，可取消）
                if (invalidReasonDTO.getFeatures() != null && invalidReasonDTO.getFeatures().size() > 0) {
                    //若类型为0检查features是否有交集（根据位置和字符串长度判断）若有则返回
                    Features features = new Features();
                    //特征内容
                    List<InvalidReasonDTO.FeaturesIn> featuresIns = invalidReasonDTO.getFeatures();
                    //过滤带有不带有特征id的特征
                    featuresIns = featuresIns.stream().filter(item -> item.getId() == null).collect(Collectors.toList());
                    //检查特征内容是否有交集（根据位置和字符串长度判断）若有则返回
                    //装载检查重复需要的类
                    CheckReFeaturesDTO checkReFeaturesDTO = new CheckReFeaturesDTO();
                    checkReFeaturesDTO.setReportId(invalidReasonDTO.getReportId());
                    checkReFeaturesDTO.setRightSort(invalidReasonDTO.getContent());
                    List<CheckReFeaturesDTO.featuresIn> checkFeatureIns = new ArrayList<>();
                    for (InvalidReasonDTO.FeaturesIn featuresIn : featuresIns) {
                        CheckReFeaturesDTO.featuresIn featuresIn1 = new CheckReFeaturesDTO.featuresIn();
                        BeanUtils.copyProperties(featuresIn, featuresIn1);
                        checkFeatureIns.add(featuresIn1);
                    }
                    checkReFeaturesDTO.setFeatures(checkFeatureIns);
                    Boolean isFlag = this.checkReFeatures(checkReFeaturesDTO);
                    if (isFlag == false) {
                        return Response.error("特征内容重复");
                    }
                    //不重复则需要入表
                    //标的专利号,权要id,特征内容,报告id
                    //通过报告id查询标的专利号
                    Integer reportId = invalidReasonDTO.getReportId();
                    LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.select(Report::getSignPatentNo);
                    queryWrapper.eq(Report::getId, reportId);
                    Report report = reportService.getOne(queryWrapper);
                    features.setSignPatentNo(report.getSignPatentNo());
                    //权要id（DTO类的content字段）
                    features.setRightId(invalidReasonDTO.getContent());
                    //报告id
                    features.setReportId(reportId);
                    //遍历特征内容集合，保存到表（类型为0）
                    for (int i = 0; i < featuresIns.size(); i++) {
                        //若类型为0,保存到特征表
                        InvalidReasonDTO.FeaturesIn featuresIn = featuresIns.get(i);
                        features.setContent(featuresIn.getFeatureStr());
                        features.insert();
                        //若类型为0,保存到特征与位置关联表(特征id,位置)
                        AssoPositionFeatures assoPositionFeatures = new AssoPositionFeatures();
                        assoPositionFeatures.setFeaturesID(features.getId());
                        assoPositionFeatures.setPosition(featuresIn.getPosition());
                        assoPositionFeatures.insert();
                    }
                }
                //判断是否传入特征集合 (更新无特征更新，可取消）
            } else {
                return Response.error("相关证据不能为空");
            }
        } else if (invalidName.equals(2) || invalidName.equals(3)) {//若类型为2,3则proofGroups不能为空
            if (invalidReasonDTO.getProofGroups() != null) {
                //复制DTO类字段到InvalidReason实体类并保存入库
                BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
                invalidReason.updateById();
                //删除无效理由的证据组合
                proofGroupService.deleteProofGroupByInvalid(invalidReason.getId());
                //根据proofGroups保存proofGroup
                List<ProofGroupDTO> proofGroupDTOS = new ArrayList<>();
                for (InvalidReasonDTO.ProofGroupIn proofGroupIn : invalidReasonDTO.getProofGroups()) {
                    ProofGroupDTO proofGroupDTO = new ProofGroupDTO();
                    proofGroupDTO.setInvalidReasonId(invalidReason.getId());//无效理由id
                    proofGroupDTO.setDescription(proofGroupIn.getDescription());//描述
                    proofGroupDTO.setArgumentStr(proofGroupIn.getArgumentStr());//陈述意见
                    proofGroupDTO.setGroupDetails(proofGroupIn.getGroupDetails());//证据ids
                    proofGroupDTOS.add(proofGroupDTO);
                }
                proofGroupService.addProofGroup(proofGroupDTOS);
            } else {
                return Response.error("证据组合不能为空");
            }
        }
        //添加自定义字段值
        if (invalidReasonDTO.getFields() != null) {
            invalidReasonDTO.getFields().forEach(item -> {
                item.setInvalidReasonId(invalidReason.getId());
            });
        }
        invalidReasonFieldValueService.addOrUpdate(invalidReasonDTO.getFields());
        return Response.success("更新成功");
    }

    /**
     * 查找无效理由和证据列表
     *
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public List<QueryInvalidReasonVO> queryInvalidReason(Integer reportId) {
        List<QueryInvalidReasonVO> queryInvalidReasonVOS = new ArrayList<>();
        //根据报告id查询无效理由
        List<InvalidReason> invalidReasons = new ArrayList<>();
        if (reportId != null) {
            LambdaQueryWrapper<InvalidReason> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(InvalidReason::getReportId, reportId);
            invalidReasons = this.list(queryWrapper);
        }
        for (InvalidReason invalidReason : invalidReasons) {
            QueryInvalidReasonVO queryInvalidReasonVO = new QueryInvalidReasonVO();
            BeanUtils.copyProperties(invalidReason, queryInvalidReasonVO);
            queryInvalidReasonVOS.add(queryInvalidReasonVO);
        }
        if (queryInvalidReasonVOS.size() > 0) {
            List<QueryInvalidReasonVO> queryInvalidReasonVOs = this.loadInvalidReason(queryInvalidReasonVOS);
            return queryInvalidReasonVOs;
        }
        return null;
    }

    /**
     * 查找无效理由和证据列表
     * <p>
     * 把无效理由集合装载到要返回的列表集合中
     *
     * @param queryInvalidReasonVOS
     */
    public List<QueryInvalidReasonVO> loadInvalidReason(List<QueryInvalidReasonVO> queryInvalidReasonVOS) {
        //若类型为2,3,则查询证据组合
        //查询出类型为2,3时的无效理由ids
        List<Integer> invalidReasonsIds = queryInvalidReasonVOS.stream()
                .map(QueryInvalidReasonVO::getId)
                .collect(Collectors.toList());
        //根据无效理由ids查询出所有的证据组合c
        List<ProofGroup> proofGroups = new ArrayList<>();
        if (invalidReasonsIds.size() > 0) {
            LambdaQueryWrapper<ProofGroup> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.in(ProofGroup::getInvalidReasonId, invalidReasonsIds);
            proofGroups = proofGroupService.list(queryWrapper1);
        }
        //由于查出来的proofGroups中没有proofIds这个字段，于是采用下面的方法装载成proofGroupVOS
        List<QueryInvalidReasonVO.proofGroupIn> proofGroupIns = this.loadProofGroupVO(proofGroups);
        //根据无效理由id查询自定义字段

        //根据无效理由id查询自定义字段值
        LambdaQueryWrapper<InvalidReasonFieldValue> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(InvalidReasonFieldValue::getInvalidReasonId, invalidReasonsIds);
        List<InvalidReasonFieldValueDTO> invalidReasonFieldValues = invalidReasonFieldValueService.getBaseMapper().getListByReasonIds(invalidReasonsIds);
        for (QueryInvalidReasonVO queryInvalidReasonVO : queryInvalidReasonVOS) {
            //比对无效理由id，把能匹配上的进行装载
            List<QueryInvalidReasonVO.proofGroupIn> proofGroupIn = proofGroupIns.stream()
                    .filter(item -> item.getInvalidReasonId().equals(queryInvalidReasonVO.getId()))
                    .collect(Collectors.toList());
            queryInvalidReasonVO.setProofGroups(proofGroupIn);
            List<InvalidReasonFieldValueDTO> valuesTem = invalidReasonFieldValues.stream().filter(item -> item.getInvalidReasonId().equals(queryInvalidReasonVO.getId())).collect(Collectors.toList());
            queryInvalidReasonVO.setFields(valuesTem);
        }
        return queryInvalidReasonVOS;
    }

    /**
     * 查找无效理由和证据列表
     * <p>
     * 把查出来的所有证据组合实体类集合转成VO类集合
     *
     * @param proofGroups
     */
    public List<QueryInvalidReasonVO.proofGroupIn> loadProofGroupVO(List<ProofGroup> proofGroups) {
        List<QueryInvalidReasonVO.proofGroupIn> proofGroupIns = new ArrayList<>();
        //根据传入的proofGroups对象集合，过滤出所有的ids
        List<Integer> proofGroupIds = proofGroups.stream()
                .map(ProofGroup::getId)
                .collect(Collectors.toList());
        //根据组合ids查询出每一个groupId对应的proofIds
        //首先批量查出来所有的证据和证据组合关联对象
        List<AssoProofGroup> assoProofGroups = new ArrayList<>();
        if (proofGroupIds.size() > 0) {
            LambdaQueryWrapper<AssoProofGroup> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.in(AssoProofGroup::getGroupId, proofGroupIds);
            assoProofGroups = assoProofGroupService.list(queryWrapper);
        }
        //证据组合的装载
        for (ProofGroup proofGroup : proofGroups) {
            QueryInvalidReasonVO.proofGroupIn proofGroupIn = new QueryInvalidReasonVO.proofGroupIn();
            //基本信息装载
            proofGroupIn.setInvalidReasonId(proofGroup.getInvalidReasonId());
            proofGroupIn.setDescription(proofGroup.getDescription());
            proofGroupIn.setArgument_str(proofGroup.getArgumentStr());
            List<Integer> proofIds = assoProofGroups.stream().filter(item -> item.getGroupId().equals(proofGroup.getId())).map(AssoProofGroup::getProofId).collect(Collectors.toList());
            //根据证据id查询证据
            List<CompareFiles> proofs = new ArrayList<>();
            if (proofIds.size() > 0) {
                LambdaQueryWrapper<CompareFiles> proofLambdaQueryWrapper = new LambdaQueryWrapper<CompareFiles>();
                proofLambdaQueryWrapper.in(CompareFiles::getId, proofIds);
                proofs = compareFilesService.list(proofLambdaQueryWrapper);
            }
            List<QueryInvalidReasonVO.proofIn> proofIns = new ArrayList<>();
            proofs.forEach(item -> {
                QueryInvalidReasonVO.proofIn proof = new QueryInvalidReasonVO.proofIn();
                proof.setId(item.getId());
                proof.setSort(item.getSysOrder());
                proof.setPatentNo(item.getPatentNo());
                proof.setFileId(item.getFileId());
                proof.setFileType(item.getFileType());
                proofIns.add(proof);
            });
            proofGroupIn.setProofIds(proofIds);
            proofIns.sort(Comparator.comparing(QueryInvalidReasonVO.proofIn::getSort));
            proofGroupIn.setProofs(proofIns);
            proofGroupIns.add(proofGroupIn);
        }
        return proofGroupIns;
    }

    /**
     * 查询无效理由和证据的详情
     *
     * @param id
     * @return
     * @throws IOException
     */
    public String queryInvalidReasonDetail(Integer id) throws IOException {
        QueryInvalidReasonVO queryInvalidReasonVO = new QueryInvalidReasonVO();
        if (id != null && id > 0) {
            //根据id查询无效理由
            InvalidReason invalidReason = this.getById(id);
            if (invalidReason == null) {
                return Response.error("没查到无效理由");
            }
            //将初步查出来的无效理由赋值给要返回的VO类
            BeanUtils.copyProperties(invalidReason, queryInvalidReasonVO);
            Integer invalidName = invalidReason.getInvalidName();
            if (invalidName == null) {
                return Response.error("没查到类型");
            }
            //若类型为0，则查询出特征并且装载
            if (invalidName.equals(0)) {
                //获取报告id和权要排序字段
                Integer reportId = invalidReason.getReportId();
                Integer rightSort = invalidReason.getRightSort();
                if (reportId != null && rightSort != null) {
                    //调用装载特征的方法
                    List<QueryInvalidReasonVO.featuresIn> featuresIns = this.loadFeature(reportId, rightSort);
                    //赋值
                    queryInvalidReasonVO.setFeatures(featuresIns);
                }
            } else if (invalidName.equals(2) || invalidName.equals(3)) { //若类型为2,3则查询证据组合并装载
                //根据无效理由id查询出proofGroup集合
                Integer invalidReasonId = invalidReason.getId();
                //调用装载证据组合方法
                List<QueryInvalidReasonVO.proofGroupIn> proofGroupIns = this.loadProofGroup(invalidReasonId);
                queryInvalidReasonVO.setProofGroups(proofGroupIns);
            } else {
                return Response.error("无效类型错误");
            }
            //根据无效理由id查询自定义字段值
            LambdaQueryWrapper<InvalidReasonFieldValue> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(InvalidReasonFieldValue::getInvalidReasonId, id);
            List<InvalidReasonFieldValue> invalidReasonFieldValues = invalidReasonFieldValueService.list(wrapper);
            List<InvalidReasonFieldValueDTO> list = new ArrayList<>();
            invalidReasonFieldValues.forEach(item -> {
                InvalidReasonFieldValueDTO invalidReasonFieldValueDTO = new InvalidReasonFieldValueDTO();
                invalidReasonFieldValueDTO.setInvalidReasonId(item.getInvalidReasonId());
                invalidReasonFieldValueDTO.setFieldValue(item.getFieldValue());
                invalidReasonFieldValueDTO.setFieldId(item.getInvalidReasonFieldId());
                list.add(invalidReasonFieldValueDTO);
            });
            queryInvalidReasonVO.setFields(list);
            //查出来的无效理由可以直接返回
            return Response.success(queryInvalidReasonVO);
        } else {
            return Response.error("未传入参数");
        }
    }

    /**
     * 装载特征集合
     *
     * @param reportId
     * @param rightSort
     * @return
     */
    public List<QueryInvalidReasonVO.featuresIn> loadFeature(Integer reportId, Integer rightSort) {
        //需要装载的某个无效理由的特征集合
        List<QueryInvalidReasonVO.featuresIn> featuresIns = new ArrayList<>();
        //通过报告id查询标的专利号
        LambdaQueryWrapper<Report> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Report::getId, reportId);
        Report report = reportService.getOne(queryWrapper);
        //获取标的专利号
        String signPatentNo = report.getSignPatentNo();
        //根据标的专利号、报告id、权要排序查询出特征集合
        LambdaQueryWrapper<Features> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(Features::getReportId, reportId)
                .eq(Features::getSignPatentNo, signPatentNo)
                .eq(Features::getRightId, rightSort);
        List<Features> featuress = featureService.list(queryWrapper1);
        //遍历特征集合
        for (Features features : featuress) {
            //需要装载的某个无效理由的每个特征
            QueryInvalidReasonVO.featuresIn featuresIn = new QueryInvalidReasonVO.featuresIn();
            featuresIn.setFeatureStr(features.getContent());
            //需要根据特征id查询出它的初始位置
            Integer featureId = features.getId();
            LambdaQueryWrapper<AssoPositionFeatures> queryWrapper2 = new LambdaQueryWrapper<>();
            queryWrapper2.eq(AssoPositionFeatures::getFeaturesID, featureId);
            AssoPositionFeatures assoPositionFeatures = assoPositionFeaturesService.getOne(queryWrapper2);
            featuresIn.setPosition(assoPositionFeatures.getPosition());
            featuresIns.add(featuresIn);
        }
        return featuresIns;
    }

    /**
     * 装载证据组合
     *
     * @param invalidReasonId
     * @return
     */
    public List<QueryInvalidReasonVO.proofGroupIn> loadProofGroup(Integer invalidReasonId) {
        List<QueryInvalidReasonVO.proofGroupIn> proofGroupIns = new ArrayList<>();
        //根据无效理由id查询出证据组合集合
        LambdaQueryWrapper<ProofGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProofGroup::getInvalidReasonId, invalidReasonId);
        List<ProofGroup> proofGroups = proofGroupService.list(queryWrapper);
        if (proofGroups != null && proofGroups.size() > 0) {
            //遍历证据组合集合
            for (ProofGroup proofGroup : proofGroups) {
                QueryInvalidReasonVO.proofGroupIn proofGroupIn = new QueryInvalidReasonVO.proofGroupIn();
                proofGroupIn.setDescription(proofGroup.getDescription());
                proofGroupIn.setArgument_str(proofGroup.getArgumentStr());
                //组合id
                Integer groupId = proofGroup.getId();
                LambdaQueryWrapper<AssoProofGroup> queryWrapper1 = new LambdaQueryWrapper<>();
                queryWrapper1.eq(AssoProofGroup::getGroupId, groupId);
                List<AssoProofGroup> assoProofGroups = assoProofGroupService.list(queryWrapper1);
                //取出证据ids
                List<Integer> proofIds = assoProofGroups.stream().map(AssoProofGroup::getProofId).collect(Collectors.toList());
                proofGroupIn.setProofIds(proofIds);
                proofGroupIns.add(proofGroupIn);
            }
            return proofGroupIns;
        } else {
            return null;
        }
    }


    @Transactional(rollbackFor = Exception.class)
    public String updateArgumentStr(UpdateArgumentStrDTO updateArgumentStrDTO) {
        Integer invalidReasonId = updateArgumentStrDTO.getId();
        String argumentStr = updateArgumentStrDTO.getArgumentStr();
        if (invalidReasonId == null) {

            return Response.error("请选择无效理由");
        }
        InvalidReason invalidReason = this.getById(invalidReasonId);
        invalidReason.setArgumentStr(argumentStr);
        invalidReason.updateById();
        return Response.success("修改成功");
    }
    /**
     * 导出无效理由所需的查询
     *
     * @param reportId
     * @return
     */
    public List<ExportInvalidReasonVO> exportInvalidReason(Integer reportId) {
        List<ExportInvalidReasonVO> exportInvalidReasonVOS = new ArrayList<>();
        //根据报告id查询出所有无效理由,无效理由(0权利要求不清楚 1说明书公开不充分 2不具备创造性 3不具备新颖性）
        LambdaQueryWrapper<InvalidReason> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(InvalidReason::getReportId, reportId);
        List<InvalidReason> invalidReasons = this.list(queryWrapper);
        for (InvalidReason invalidReason : invalidReasons) {
            if (invalidReason != null) {
                ExportInvalidReasonVO exportInvalidReasonVO = this.invalidReasonToExport(invalidReason);
                exportInvalidReasonVOS.add(exportInvalidReasonVO);
            }
        }
        return exportInvalidReasonVOS;
    }

    /**
     * 根据无效理由对象转换成返回的VO类
     *
     * @param invalidReason
     * @return
     */
    public ExportInvalidReasonVO invalidReasonToExport(InvalidReason invalidReason) {
        ExportInvalidReasonVO exportInvalidReasonVO = new ExportInvalidReasonVO();
        //陈述意见
        exportInvalidReasonVO.setArgumentStr(invalidReason.getArgumentStr());
        Integer invalidName = invalidReason.getInvalidName();
        //无效理由类型为0，为权利要求不清楚
        if (invalidName.equals(0)) {
            //无效理由
            exportInvalidReasonVO.setInvalidName(invalidName);
            //涉及内容(权要排序)
            exportInvalidReasonVO.setContent(invalidReason.getRightSort());
            //相关证据
            exportInvalidReasonVO.setProofStr(invalidReason.getProofStr());

            return exportInvalidReasonVO;
        } else if (invalidName.equals(1)) {//无效理由类型为1，为说明书公开不充分
            //无效理由
            exportInvalidReasonVO.setInvalidName(invalidName);
            //涉及内容(说明书为-1)
            exportInvalidReasonVO.setContent(-1);
            //相关证据
            exportInvalidReasonVO.setProofStr(invalidReason.getProofStr());
            return exportInvalidReasonVO;
        } else if (invalidName.equals(2) || invalidName.equals(3)) {//无效理由类型为2，为不具备创造性；无效理由类型为3，为不具备新颖性
            //无效理由
            exportInvalidReasonVO.setInvalidName(invalidName);
            //涉及内容(权要排序)
            exportInvalidReasonVO.setContent(invalidReason.getRightSort());
            //相关证据是证据组合字符串
            Integer invalidReasonId = invalidReason.getId();
            String proofStr = this.proofGroupToString(invalidReasonId);
            exportInvalidReasonVO.setProofStr(proofStr);
            return exportInvalidReasonVO;
        } else {
            return null;
        }
    }
    /**
     * 根据无效理由id，返回相关证据的字符串
     *
     * @param invalidReasonId
     * @return
     */
    public String proofGroupToString(Integer invalidReasonId) {
        //1.根据无效理由id查询出多个证据组合id
        LambdaQueryWrapper<ProofGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProofGroup::getInvalidReasonId, invalidReasonId);
        List<ProofGroup> proofGroups = proofGroupService.list(queryWrapper);
        List<Integer> proofGroupIds = proofGroups.stream().map(ProofGroup::getId).collect(Collectors.toList());
        //2.根据每个证据组合id到关联表中查询出所有的证据ids，并拼接成字符串
        LambdaQueryWrapper<AssoProofGroup> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.in(AssoProofGroup::getGroupId, proofGroupIds);
        List<AssoProofGroup> assoProofGroups = assoProofGroupService.list(queryWrapper1);
        List<String> results = new ArrayList<>();
        StringBuilder SB = new StringBuilder();
        for (Integer proofGroupId : proofGroupIds) {
            List<Integer> proofIds = assoProofGroups.stream().filter(item -> item.getGroupId().equals(proofGroupId)).map(AssoProofGroup::getProofId).collect(Collectors.toList());
            //3.根据证据ids，到证据表中查询出所有证据，并拼接成字符串
            if (proofIds.size() > 0) {
                //根据证据ids查询证据排序字段
                LambdaQueryWrapper<CompareFiles> queryWrapper2 = new LambdaQueryWrapper<CompareFiles>();
                queryWrapper2.in(CompareFiles::getId, proofIds);
                List<CompareFiles> proofs = compareFilesService.list(queryWrapper2);
                List<Integer> sysorders = proofs.stream().map(CompareFiles::getSysOrder).collect(Collectors.toList());
                StringBuilder sb = new StringBuilder();
                for (Integer sysorder : sysorders) {
                    sb.append("证据").append(sysorder).append("+");
                }
                sb.deleteCharAt(sb.length() - 1);
                sb.append("\n");
                String result = sb.toString();
                results.add(result);
            }
        }
        for (String resultStr : results) {
            SB.append(resultStr);
        }
        String STR = SB.toString();
        return STR;
    }

}