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

import cn.cslg.report.common.model.dto.FeaturesDTO;
import cn.cslg.report.common.model.dto.invalidReReport.ArgumentsDTO;
import cn.cslg.report.common.model.dto.invalidReReport.ArgumentsDetailsDTO;
import cn.cslg.report.common.model.dto.invalidReReport.ArgumentsListDTO;
import cn.cslg.report.common.model.vo.invalidReReport.ArgumentsDetailsVO;
import cn.cslg.report.common.model.vo.invalidReReport.ArgumentsListVO;
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.PatentRight;
import cn.cslg.report.entity.Report;
import cn.cslg.report.entity.invalidReReport.*;
import cn.cslg.report.mapper.InvalidReReport.ArgumentsMapper;

import cn.cslg.report.service.business.CompareFilesService;
import cn.cslg.report.service.business.FeatureService;
import cn.cslg.report.service.business.ReportService;

import com.alibaba.fastjson.JSONObject;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;


@Service
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ArgumentsService extends ServiceImpl<ArgumentsMapper, Arguments> {
    private final LoginUtils loginUtils;
    private final ScratchService scratchService;
    private final AssoArgumentsService assoArgumentsService;
    private final FeatureService featureService;
    private final ProofStrService assoFeatureProofService;
    private final ArgumentsService argumentsService;
    private final ReportService reportService;
    private final CompareFilesService compareFilesService;
    private final ProofStrService proofStrService;

    /**
     * 添加陈述意见
     *
     * @param argumentsDTO
     */
    public String addArguments(ArgumentsDTO argumentsDTO) throws IOException {
        Integer proofStrId = argumentsDTO.getProofStrId();
        Integer argumentId =argumentsDTO.getArgumentId();
        // 检验参数
        if (argumentsDTO == null || argumentsDTO.getReportId() == null || argumentsDTO.getRightId() == null || argumentsDTO.getProofId() == null || argumentsDTO.getProofStr() == null) {
            return Response.error("参数不正确");
        }
        if (argumentsDTO.getFeatureId() == null) {
            FeaturesDTO featuresDTO = new FeaturesDTO();
            featuresDTO.setReportId(argumentsDTO.getReportId());
            featuresDTO.setRightId(argumentsDTO.getRightId());
            featuresDTO.setContent(argumentsDTO.getFeatureContent());
            String ret = featureService.addSingleFeature(featuresDTO);
            Response response = JSONObject.parseObject(ret, Response.class);
            if (response.getCode().equals(0)) {
                return ret;
            } else {
                argumentsDTO.setFeatureId(Integer.parseInt(response.getData().toString()));
            }
        }
        //添加或更新无效证据
        ProofStr proof = new ProofStr();
        if (proofStrId == null) {
            proof.setFeatureId(argumentsDTO.getFeatureId());
            proof.setCompareFileId(argumentsDTO.getProofId());
            proof.setProofStr(argumentsDTO.getProofStr());
            proof.setReportId(argumentsDTO.getReportId());
            proof.setRightSort(argumentsDTO.getRightId());
            proof.insert();
        } else {
            proof = proofStrService.getById(proofStrId);
            proof.setProofStr(argumentsDTO.getProofStr());
            proof.updateById();
        }
        if (argumentsDTO.getArgumentStr() != null) {
            Integer loginId = loginUtils.getId();
            //装载陈述意见实体类
            Arguments arguments = new Arguments();
            if ( argumentId== null) {
                BeanUtils.copyProperties(argumentsDTO, arguments);
                arguments.setCreateId(loginId);
                arguments.setProofStrId(proof.getId());
                arguments.setRightSort(argumentsDTO.getRightId());
                arguments.insert();
            } else {
                arguments = this.getById(argumentId);
                BeanUtils.copyProperties(argumentsDTO,arguments);
                arguments.setProofStrId(proof.getId());
                arguments.setRightSort(argumentsDTO.getRightId());
                arguments.updateById();
            }

            //若划词不为空
            if (argumentsDTO.getContent() != null) {
                Scratch scratch = new Scratch();
                BeanUtils.copyProperties(argumentsDTO, scratch);
                //根据证据类型获得证据的专利号
                CompareFiles compareFiles = compareFilesService.getById(arguments.getProofId());
                String patenNo = compareFiles.getPatentNo();
                scratch.setPatentNo(patenNo);
                scratch.setCreateId(loginId);
                scratch.setArgumentId(arguments.getId());
                scratch.setReportId(argumentsDTO.getReportId());
                scratch.setScratchColor(argumentsDTO.getColor());
                scratch.insert();
            }
        }
        return Response.success("添加成功");
    }

    /**
     * 删除陈述意见详情
     *
     * @param argumentsIds
     */
    public void deleteArguments(List<Integer> argumentsIds) {
        //判断argumentsId是否为空
        if (argumentsIds == null || argumentsIds.size() == 0) {
            return;
        }
        //判断陈述意见方案中是否有正在使用的陈述意见
        LambdaQueryWrapper<AssoArguments> assoArgumentsWrapper = new LambdaQueryWrapper<>();
        assoArgumentsWrapper.in(AssoArguments::getArgumentId, argumentsIds);
        List<AssoArguments> assoArguments = assoArgumentsService.list(assoArgumentsWrapper);
        if (assoArguments.size() > 0) {
            return;
        }
        //根据argumentsId查询陈述意见
        LambdaQueryWrapper<Arguments> argumentsWrapper = new LambdaQueryWrapper<>();
        argumentsWrapper.in(Arguments::getId, argumentsIds);
        List<Arguments> arguments = this.list(argumentsWrapper);
        List<Integer> proofIds = arguments.stream().map(Arguments::getProofId).collect(Collectors.toList());
        //根据proofIds获得proof
        LambdaQueryWrapper<CompareFiles> proofWrapper = new LambdaQueryWrapper<>();
        proofWrapper.in(CompareFiles::getId, proofIds);
        List<CompareFiles> proofs = compareFilesService.list(proofWrapper);
        List<String> patentNos = proofs.stream().map(CompareFiles::getPatentNo).collect(Collectors.toList());
        if (patentNos.size() > 0) {
            //根据专利号和报告id获得划词内容
            LambdaQueryWrapper<Scratch> scratchLambdaQueryWrapper = new LambdaQueryWrapper<>();
            scratchLambdaQueryWrapper.in(Scratch::getPatentNo, patentNos);
            scratchLambdaQueryWrapper.eq(Scratch::getReportId, arguments.get(0).getReportId());
            scratchService.remove(scratchLambdaQueryWrapper);
        }
        this.remove(argumentsWrapper);
        return;
    }

    /**
     * 查询划词陈述意见
     *
     * @param
     */
    public List<ArgumentsDetailsVO> queryScratchs(Integer fileId) {
        List<ArgumentsDetailsVO> argumentsDetailsVOS = new ArrayList<>();
        //根据文件id查询文件
        CompareFiles compareFiles = compareFilesService.getById(fileId);
        String patentNo = compareFiles.getPatentNo();
        //根据报告id获得标的专利号
        Report report = reportService.getById(compareFiles.getReportId());
        Integer reportId = report.getId();
        String signPatentNo = report.getSignPatentNo();
        // 根据报告id和权要id获得所有特征
        LambdaQueryWrapper<Features> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Features::getReportId, reportId);
        List<Features> features = featureService.list(wrapper);
        List<Integer> featureIds = features.stream().map(Features::getId).collect(Collectors.toList());

        //根据特征和文件id获得证据
        LambdaQueryWrapper<ProofStr> featureProofWrapper = new LambdaQueryWrapper<>();
        featureProofWrapper.in(ProofStr::getFeatureId, featureIds)
                .eq(ProofStr::getCompareFileId, fileId);
        List<ProofStr> proofStrs = assoFeatureProofService.list(featureProofWrapper);
        //查询划词信息
        LambdaQueryWrapper<Scratch> scratchLambdaQueryWrapper = new LambdaQueryWrapper<>();
        scratchLambdaQueryWrapper.eq(Scratch::getPatentNo, patentNo);
        scratchLambdaQueryWrapper.eq(Scratch::getReportId, reportId);
        List<Scratch> scratchList = scratchService.list(scratchLambdaQueryWrapper);
        //获得陈述意见
        List<Arguments> arguments = new ArrayList<>();
        List<Integer> argumentIds = scratchList.stream().map(Scratch::getArgumentId).collect(Collectors.toList());
        if (argumentIds.size() > 0) {
            LambdaQueryWrapper<Arguments> wrapper1 = new LambdaQueryWrapper<>();
            wrapper1.in(Arguments::getId, argumentIds);
            arguments = argumentsService.list(wrapper1);
        }
        for (Scratch item : scratchList) {
            ArgumentsDetailsVO argumentsDetailsVO = new ArgumentsDetailsVO();
            argumentsDetailsVO.setColor(item.getScratchColor());
            argumentsDetailsVO.setSortStr("D" + (compareFiles.getSysOrder()));
            Arguments argument = arguments.stream().filter(tem -> tem.getId().equals(item.getArgumentId())).findFirst().orElse(null);
            BeanUtils.copyProperties(argument, argumentsDetailsVO);
            BeanUtils.copyProperties(item, argumentsDetailsVO);
            ProofStr proofStr = proofStrs.stream().filter(tem -> tem.getFeatureId().equals(argument.getFeatureId())).findFirst().orElse(null);
            if (proofStr != null) {
                argumentsDetailsVO.setProofStr(proofStr.getProofStr());
                argumentsDetailsVO.setProofStrId(proofStr.getId());
            }
            argumentsDetailsVOS.add(argumentsDetailsVO);
        }
        return argumentsDetailsVOS;
    }

    /**
     * 添加陈述意见
     *
     * @param argumentsDTO
     * @return
     */
    public String updateArgument(ArgumentsDetailsDTO argumentsDTO) {
        Integer proofStrId = argumentsDTO.getProofStrId();
        // 检验参数
        if (argumentsDTO == null || argumentsDTO.getReportId() == null || argumentsDTO.getFeatureId() == null || argumentsDTO.getRightSort() == null || argumentsDTO.getProofId() == null) {
            return Response.error("参数不正确");
        }
        //根据划词id查询划词信息
        Integer scratchId = argumentsDTO.getId();
        //根据划词id获得划词信息
        Scratch scratch = scratchService.getById(scratchId);
        //装载划词信息并更新
        scratch.setScratchColor(argumentsDTO.getColor());
        scratch.setScratchType(argumentsDTO.getScratchType());
        scratch.updateById();
        //根据陈述意见id更新陈述意见
        if (scratchId != null) {
            Arguments arguments = this.getById(scratch.getArgumentId());
            arguments.setArgumentStr(argumentsDTO.getArgumentStr());
            arguments.setRightSort(argumentsDTO.getRightSort());
            arguments.setFeatureId(argumentsDTO.getFeatureId());
            arguments.updateById();
        }

        ProofStr proofStr = proofStrService.getById(proofStrId);
        proofStr.setProofStr(argumentsDTO.getProofStr());
        proofStr.updateById();
        return Response.success("修改成功");
    }

    /**
     * 根据文件id和权要sort查询列表
     *
     * @param
     */
    public List<ArgumentsListVO> queryPoofArguments(Integer fileId, Integer rightSort, Integer reportId) throws IOException {
        PatentRight patentRight = this.getPatentRight(reportId, rightSort);
        List<ArgumentsListVO> argumentsListVOS = new ArrayList<>();
        // 根据报告id和权要id获得所有特征
        LambdaQueryWrapper<Features> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Features::getReportId, reportId)
                .eq(Features::getRightId, rightSort);
        List<Features> features = featureService.list(wrapper);
        List<Integer> featureIds = features.stream().map(Features::getId).collect(Collectors.toList());
        //根据特征和文件id获得证据
        LambdaQueryWrapper<ProofStr> featureProofWrapper = new LambdaQueryWrapper<>();
        featureProofWrapper.in(ProofStr::getFeatureId, featureIds)
                .eq(ProofStr::getCompareFileId, fileId);
        List<ProofStr> proofStrs = assoFeatureProofService.list(featureProofWrapper);
        //遍历装载特征和相关证据到实体类
        proofStrs.forEach(item -> {
            Features features1 = features.stream().filter(tem -> tem.getId().equals(item.getFeatureId())).findFirst().orElse(null);
            ArgumentsListVO argumentsListVO = new ArgumentsListVO();
            //装载权要
            argumentsListVO.setRightSort(patentRight.getSort());
            argumentsListVO.setRightContent(patentRight.getContent());
            argumentsListVO.setRightName("权要" + (patentRight.getSort() + 1));
            //装载特征
            argumentsListVO.setFeatureId(features1.getId());
            argumentsListVO.setFeatureContent(features1.getContent());
            argumentsListVO.setFeatureName("特征" + features1.getFeaturesOrder());
            argumentsListVO.setProofStrId(item.getId());
            argumentsListVO.setProofStr(item.getProofStr());
            argumentsListVO.setProofId(fileId);
            argumentsListVOS.add(argumentsListVO);
        });

        List<Integer> argumentsIds = proofStrs.stream().map(ProofStr::getId).collect(Collectors.toList());
        List<Arguments> arguments = new ArrayList<>();
        //根据特征和证据id获得陈述意见
        if (argumentsIds.size() > 0) {
            LambdaQueryWrapper<Arguments> argumentsWrapper = new LambdaQueryWrapper<>();
            argumentsWrapper.in(Arguments::getProofStrId, argumentsIds);
            arguments = this.list(argumentsWrapper);
        }
//装载陈述意见
        for (ArgumentsListVO item:argumentsListVOS){
            item.setArguments(new ArrayList<>());
            List<Arguments> temArguments = arguments.stream().filter(tem -> item.getProofStrId().equals(tem.getProofStrId())).collect(Collectors.toList());
            temArguments.forEach(tem -> {
                ArgumentsListVO.ArgumentIn argumentIn = new ArgumentsListVO.ArgumentIn();
                argumentIn.setArgumentStr(tem.getArgumentStr());
                argumentIn.setId(tem.getId());
                item.getArguments().add(argumentIn);
            });
        }



        return argumentsListVOS;
    }

    /**
     * 根据排序获得权利要求
     *
     * @param reportId
     * @param sort
     * @return
     * @throws IOException
     */
    private PatentRight getPatentRight(Integer reportId, Integer sort) throws IOException {
        //获得标的专利号
        Report report = reportService.getById(reportId);
        //根据标的专利号获得权要
        List<PatentRight> patentRights = featureService.getRightNames(report.getSignPatentNo());
        PatentRight patentRight = patentRights.stream().filter(item ->
                sort.equals(item.getSort())
        ).findFirst().orElse(null);
        return patentRight;
    }

    /**
     * 批量添加或者更新陈述意见和证据
     *
     * @param argumentsListDTOS
     */
    @Transactional(rollbackFor = Exception.class)
    public String addOrUpdatePoofArguments(List<ArgumentsListDTO> argumentsListDTOS) {
        //当dto的大小为0时返回
        if (argumentsListDTOS == null && argumentsListDTOS.size() <= 0) {
            return Response.error("请输入信息");
        }
//        Integer createId = loginUtils.getId();
        Integer createId = 1;
        List<ProofStr> proofStrs = new ArrayList<>();
        List<Arguments> arguments = new ArrayList<>();
        List<Integer> featureIds = new ArrayList<>();
        Integer proofId = argumentsListDTOS.get(0).getProofId();
        argumentsListDTOS.forEach(item -> {
            //获得特征ids
            featureIds.add(item.getFeatureId());
            //装载无效证据
            ProofStr proofStr = new ProofStr();
            proofStr.setCompareFileId(item.getProofId());
            proofStr.setId(item.getProofStrId());
            proofStr.setProofStr(item.getProofStr());
            proofStr.setFeatureId(item.getFeatureId());
            proofStrs.add(proofStr);
            //装载陈述意见
            List<ArgumentsListDTO.ArgumentIn> argumentIns = item.getArguments();
            argumentIns.forEach(tem -> {
                Arguments argument = new Arguments();
                argument.setCreateId(createId);
                argument.setFeatureId(item.getFeatureId());
                argument.setArgumentStr(tem.getArgumentStr());
                argument.setId(tem.getId());
                argument.setProofId(item.getProofId());
                argument.setRightSort(item.getRightSort());
                argument.setReportId(item.getReportId());
                arguments.add(argument);
            });
        });
        this.deleteOrUpdateArguments(arguments, featureIds, proofId);
        if (!this.deleteOrUpdateProofStr(proofStrs, featureIds, proofId)) {
            return Response.error("同一特征有多个证据");
        }

        return Response.success("添加成功");
    }


    /**
     * 批量添加或者更新陈述意见
     *
     * @param
     */
    public void deleteOrUpdateArguments(List<Arguments> arguments, List<Integer> featureIds, Integer proofId) {
        LambdaQueryWrapper<Arguments> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Arguments::getFeatureId, featureIds)
                .eq(Arguments::getProofId, proofId);
        List<Arguments> dbArguments = this.list(wrapper);
        //作差获得要删除的陈述意见
        List<Integer> dbIds = dbArguments.stream().map(Arguments::getId).collect(Collectors.toList());
        List<Integer> ids = arguments.stream().map(Arguments::getId).collect(Collectors.toList());
        List<Integer> removeIds = dbIds;
        removeIds.removeAll(ids);
        //删除陈述意见
        if (removeIds.size() > 0) {
            this.deleteArguments(removeIds);
        }
        this.saveOrUpdateBatch(arguments);

    }

    /**
     * 批量删除或者更新证据详情
     *
     * @param proofStrs
     * @param featureIds
     * @param proofId
     * @return
     */
    public boolean deleteOrUpdateProofStr(List<ProofStr> proofStrs, List<Integer> featureIds, Integer proofId) {
        LambdaQueryWrapper<ProofStr> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(ProofStr::getFeatureId, featureIds)
                .eq(ProofStr::getCompareFileId, proofId);
        List<ProofStr> dbProofStr = assoFeatureProofService.list(wrapper);
        //作差获得要删除的相关证据
        List<Integer> dbIds = dbProofStr.stream().map(ProofStr::getId).collect(Collectors.toList());
        List<Integer> ids = proofStrs.stream().map(ProofStr::getId).collect(Collectors.toList());
        List<Integer> removeIds = dbIds;
        removeIds.removeAll(ids);
        //检查一个特征是否有多个陈述证据
        for (ProofStr item : proofStrs) {
            {
                //查询是否存在多个相同
                List<ProofStr> proofs1Str = proofStrs.stream().filter(tem ->
                        item.getFeatureId().equals(tem.getFeatureId())
                                && item.getCompareFileId().equals(tem.getCompareFileId())).collect(Collectors.toList());
                if (proofs1Str.size() > 1) {
                    return false;
                }
            }
        }
        //删除陈述意见
        assoFeatureProofService.removeByIds(removeIds);
        assoFeatureProofService.saveOrUpdateBatch(proofStrs);

        return true;
    }


    public static void main(String[] args) {
        String a = Response.error();
        Response av = JSONObject.parseObject(a, Response.class);
        System.out.println(av.getCode());
    }
}