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

import cn.cslg.report.common.model.dto.ShareReportDTO;
import cn.cslg.report.common.model.dto.invalidReReport.CheckReFeaturesDTO;
import cn.cslg.report.common.model.dto.invalidReReport.InvalidReasonDTO;
import cn.cslg.report.common.model.dto.invalidReReport.ProofGroupDTO;
import cn.cslg.report.common.model.vo.invalidReReport.QueryAllFeaturesVO;
import cn.cslg.report.common.utils.Response;
import cn.cslg.report.entity.Features;
import cn.cslg.report.entity.Report;
import cn.cslg.report.entity.invalidReReport.AssoPositionFeatures;
import cn.cslg.report.entity.invalidReReport.InvalidReason;
import cn.cslg.report.entity.invalidReReport.ProofGroup;
import cn.cslg.report.exception.XiaoShiException;
import cn.cslg.report.mapper.FeatureMapper;
import cn.cslg.report.mapper.InvalidReReport.InvalidReasonMapper;
import cn.cslg.report.service.business.ReportService;
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 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 FeatureMapper featureMapper;
    private final ProofGroupService proofGroupService;

    /**
     * 判断特征是否有重复的方法
     * @param checkReFeaturesDTO
     */
    public Boolean checkReFeatures(CheckReFeaturesDTO checkReFeaturesDTO){
        //查出表中制定报告和权要的全部特征内容和位置
         List<QueryAllFeaturesVO> queryAllFeaturesVOS = featureMapper.queryAllFeatures(checkReFeaturesDTO.getReportId(), checkReFeaturesDTO.getRightId());
        //List<QueryAllFeaturesVO> list = queryAllFeaturesVOS.stream().sorted(Comparator.comparing(QueryAllFeaturesVO::getPosition)).collect(Collectors.toList());
        //取出需要插入的特征内容和位置
        List<InvalidReasonDTO.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 {
                throw new XiaoShiException("未查询到位置");
            }
        }
        //遍历装载需要插入的特征内容和位置
        for(InvalidReasonDTO.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(InvalidReasonDTO.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 = map.get(preFeaInitialPos);
            //前面一个特征的末尾位置
            Integer preEndPosition = preFeaInitialPos + preLength -1;
            //后面一个特征内容的初始位置
            Integer nextFeaInitialPos = index < positions.size() - 1 ? positions.get(index + 1) : -1;
            //判断是否与前面一个特征内容重复（前面一个特征内容的末尾位置如果比插入的特征内容的初始位置大，则重复了）
            if(preEndPosition > featuresIn.getPosition()){
                return false;
            } else if(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();
        //若类型为1，则为说明书公开不充分
        //涉及内容为说明书，手动输入无效证据
        if(invalidName.equals(1)) {
            BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
            invalidReason.insert();
        }
        //若类型为0、2、3
        if(invalidReasonDTO.getInvalidName().equals(0) || invalidReasonDTO.getInvalidName().equals(2) || invalidReasonDTO.getInvalidName().equals(3)) {
            //则选择特征不能为空
            if (invalidReasonDTO.getFeatures() != null) {
                //若类型为0，则为“权利要求不清楚”，需要选择涉及内容（content）并输入相关证据（proofStr）
                if(invalidName.equals(0)){
                    if(invalidReasonDTO.getProofStr() != null && invalidReasonDTO.getProofStr() != ""){
                        //复制DTO类字段到InvalidReason实体类并保存入库
                        BeanUtils.copyProperties(invalidReasonDTO, invalidReason);
                        invalidReason.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.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.setArgument_str(proofGroupIn.getArgument_str());//陈述意见
                            proofGroupDTO.setProofIds(proofGroupIn.getProofIds());//证据ids
                        }
                        proofGroupService.addProofGroup(proofGroupDTOS);
                    } else {
                        return Response.error("证据组合不能为空");
                    }
                }
                //若类型为0,2,3检查features是否有交集（根据位置和字符串长度判断）若有则返回
                Features features = new Features();
                //特征内容
                List<InvalidReasonDTO.featuresIn> featuresIns = invalidReasonDTO.getFeatures();
                //检查特征内容是否有交集（根据位置和字符串长度判断）若有则返回
                CheckReFeaturesDTO checkReFeaturesDTO = new CheckReFeaturesDTO();
                checkReFeaturesDTO.setReportId(invalidReasonDTO.getReportId());
                checkReFeaturesDTO.setRightId(invalidReasonDTO.getContent());
                checkReFeaturesDTO.setFeatures(featuresIns);
                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，2，3都可以）
                for (int i = 0; i < featuresIns.size(); i++) {
                    //若类型为0,2,3保存到特征表
                    InvalidReasonDTO.featuresIn featuresIn = featuresIns.get(i);
                    features.setContent(featuresIn.getFeatureStr());
                    features.insert();
                    //若类型为0,2,3保存到特征与位置关联表(特征id,位置)
                    AssoPositionFeatures assoPositionFeatures = new AssoPositionFeatures();
                    assoPositionFeatures.setFeaturesID(features.getId());
                    assoPositionFeatures.setPosition(featuresIn.getPosition());
                    assoPositionFeatures.insert();
                }
            } else {
                return Response.error("选择特征不能为空");
            }
            return Response.success("添加成功");
        } else {
            throw new XiaoShiException("未知无效理由类型");
        }
    }

    /**
     * 删除无效理由
     * @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(@RequestBody InvalidReasonDTO invalidReasonDTO) {
        //判断invalidName的类型
        // 若类型为2,3则proofGroups不能为空，features不能为空
        //复制DTO类字段到InvalidReason实体类并更新入库
        //若类型为2,3根据proofGroups更新 proofGroup
           //查询该无效应对报告的所有证据组合
           //过滤出proofGroups的id，和无效应对报告的所有证据组合id作差，并且删除所有的差值证据组合
          //若 proofGroups里的对象的id为空则直接插入
          //若 proofGroups里的对象的id不为空则更新
        //若类型为2,3检查features是否有交集（根据位置和字符串长度判断）若有则返回
        //查询该无效应对报告的所有特征和无效理由关联记录
        //过滤出features的id，和无效应对报告的所有特征和无效理由关联记录的特征id作差，并且删除所有的差值的特征和无效理由关联记录；
     //若类型为2,3检查id为空的features和查出来的features以及本列表中的features是否有交集（根据位置和字符串长度判断）若有则抛出异常
        //无则插入
        return Response.success();

    }

    /**
     * 更新无效理由和证据
     * @param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public  String queryInvalidReason(int reportId) {
        //根据报告id查询无效理由
        ///若类型为2,3则查询证据组合和特征并装载
        return Response.success();

    }

    public String queryInvalidReasonDetail(@RequestBody ShareReportDTO shareReportDTO) throws IOException {
        //根据报告id查询无效理由
        ///若类型为2,3则查询证据组合和特征并装载
        return Response.success();
    }
}