package cn.cslg.pas.service.upLoadPatent;

import cn.cslg.pas.common.model.dto.UploadFileDTO;
import cn.cslg.pas.common.model.outApi.PatentStarListDto;
import cn.cslg.pas.common.model.vo.KeyValueVO;
import cn.cslg.pas.common.model.vo.UploadParamsVO;
import cn.cslg.pas.common.model.vo.outApi.StarPatentVO;
import cn.cslg.pas.common.utils.FileUtils;
import cn.cslg.pas.common.utils.RemoveHtmlTagsUtils;
import cn.cslg.pas.common.utils.ThrowException;
import cn.cslg.pas.domain.*;
import cn.cslg.pas.domain.asso.TaskCondition;
import cn.cslg.pas.service.TaskService;
import cn.cslg.pas.service.UploadPatentBatchService;
import cn.cslg.pas.service.asso.TaskConditionService;
import cn.cslg.pas.service.outApi.PatentStarApiService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.net.URL;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 专利之星类型任务解析获取专利类
 *
 * @Author chenyu
 * @Date 2023/6/25
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ExcutePatentDataStar implements IExcutePatentData {
    private final PatentStarApiService patentStarApiService;
    private final FileUtils fileUtils;
    private final PantentQueueService pantentQueueService;
    private final UploadPatentBatchService uploadPatentBatchService;
    private final TaskService taskService;
    private final TaskConditionService taskConditionService;
    private Integer pTaskId = 0;
    private Integer pTaskStatus = 0;

    /**
     * 解析获取专利数据
     *
     * @param task 任务
     */
    @Override
    public void startExcute(Task task) throws IOException {

        //若本次下载任务是超过一万条专利的全部下载任务
        if (task.getEndNumber() == 50) {
            try {
                Integer total = task.getTotal();
                String orderBy = task.getOrderBy();  //排序字段
                String orderByType = task.getOrderByType();  //排序类型
                String dbType = task.getDBType();  //检索数据库类型
                List<String> cells = task.getConfigCells();  //下载字段
                Integer startNumber = task.getStartNumber();  //下载起始条数位置
                List<String> isDeletePatentNos = task.getIsDeletePatentNos();  //起止条数中不需要下载的专利号

                //多个检索式
                ArrayList<MultipleCondition> multipleConditions = new ArrayList<>();
                multipleConditions.add(new MultipleCondition().setConditions("AD=20230511 AND TI=(计算机 OR 手机)").setTotal(26));
                multipleConditions.add(new MultipleCondition().setConditions("AD=20230512 AND TI=(计算机 OR 手机)").setTotal(15));
                multipleConditions.add(new MultipleCondition().setConditions("AD=20230531 AND TI=(计算机 OR 手机)").setTotal(16));

                //第一层遍历多个检索式，第二层遍历每个检索式检索出的检索页数，第三层遍历每页专利
                int lastH, lastI, lastJ;
                //若本次下载是暂停后继续，则取出上一次遍历位置信息
                if (task.getContinueLastInformation() != null && !task.getContinueLastInformation().equals("")) {
                    String[] lastIndexArr = task.getContinueLastInformation().split("\\|");
                    lastH = Integer.parseInt(lastIndexArr[0]);
                    lastI = Integer.parseInt(lastIndexArr[1]);
                    lastJ = Integer.parseInt(lastIndexArr[2]);
                } else {
                    lastH = 0;
                    lastI = 0;
                    lastJ = 0;
                }

                for (int h = lastH; h < multipleConditions.size(); h++) {
                    Calculate calculate = calculateFromStartAndEndNumber(1, multipleConditions.get(h).getTotal());
                    //根据计算出的起止页数，一页一页检索
                    for (int i = lastI; i <= calculate.getEndPage(); i++) {
                        PatentStarListDto patentStarListDto = new PatentStarListDto()
                                .setCurrentQuery(multipleConditions.get(h).getConditions())
                                .setOrderBy(orderBy)
                                .setOrderByType(orderByType)
                                .setPageNum(i + 1)
                                .setRowCount(50)
                                .setDBType(dbType);
                        //调用一般接口返回一批专利著录相关数据
                        Map<String, Object> resultMap = patentStarApiService.patentStarSearchApi(patentStarListDto);
                        if (resultMap == null || (Integer) resultMap.get("total") == 0) {
                            ThrowException.throwXiaoShiException("未检索到相关专利");
                        }

                        List<StarPatentVO> starPatents = (List<StarPatentVO>) resultMap.get("records");
                        //遍历这一页的专利
                        for (int j = lastJ; j < starPatents.size(); j++) {
                            //若任务状态为已暂停，则将当前三层循环的位置信息保存入任务条件表，并结束本次任务的下载
                            if (pTaskId.equals(task.getId()) && pTaskStatus == 4) {
                                TaskCondition taskCondition = new TaskCondition()
                                        .setId(task.getTaskConditionId())
                                        .setContinueLastInformation(h + "|" + i + "|" + j);
                                taskConditionService.updateById(taskCondition);
                                return;
                            }

                            //判断若本任务是第一次下载，并且刚检索到第一页专利
                            if (h == 0 && i == 0) {
                                //如果还没走到需要下载的专利开始位置startNumber，则跳过
                                if (j < startNumber - 1) {
                                    continue;
                                }
                            }

                            //查询当前任务完成专利数量，判断若达到total，则结束
                            if (taskService.getById(task.getId()).getSuccessNum().equals(total)) {
                                return;
                            }

                            //若当前遍历到的专利号是需要删除的专利，则跳过，不下载它
                            if (isDeletePatentNos != null && isDeletePatentNos.size() > 0 && isDeletePatentNos.contains(starPatents.get(j).getApplicationNo())) {
                                continue;
                            }

                            UploadParamsVO uploadParamsVO = new UploadParamsVO();
                            Patent patent = new Patent();
                            uploadParamsVO.setPatent(patent);
                            uploadParamsVO.getPatent().setPatentNo(starPatents.get(j).getPatentNo());
                            uploadPatentBatchService.getOneOrInsertOne(uploadParamsVO);

                            PQueueData pQueueData = new PQueueData()
                                    .setTask(task)
                                    .setStarPatent(starPatents.get(j))
                                    .setUploadParamsVO(uploadParamsVO);

                            //专利丢入著录生产者队列，并唤醒著录生产者线程
                            if (cells.contains("1")) {
                                pantentQueueService.zhuluToPQueue(pQueueData);
                            }
                            //专利丢入权要生产者队列，并唤醒权要生产者线程
                            if (cells.contains("2")) {
                                pantentQueueService.rightToPQueue(pQueueData);
                            }
                            //专利丢入说明书文本生产者队列，并唤醒说明书文本生产者线程
                            if (cells.contains("3")) {
                                pantentQueueService.instructionTextToPQueue(pQueueData);
                            }
                            //专利丢入说明书pdf生产者队列，并唤醒说明书pdf生产者线程
                            if (cells.contains("4")) {
                                pantentQueueService.instructionPDFToPQueue(pQueueData);
                            }
                            //专利丢入摘要附图生产者队列，并唤醒摘要附图生产者线程
                            if (cells.contains("6")) {
                                pantentQueueService.imageToPQueue(pQueueData);
                            }

                        }
                    }

                }

            } catch (IOException e) {
                e.printStackTrace();
                //生产消费到一半时，发生错误异常，将任务状态置为完成
                task = taskService.getById(task.getId());
                if (task.getStatus().equals(1)) {
                    task.setStatus(2);
                    taskService.updateById(task);
                }
            }

        } else {
            excuteLessThan10000(task);
        }


    }

    private void excuteLessThan10000(Task task) {
        try {
            Integer successNum = task.getSuccessNum();  //成功条数（即上一次下载到的位置）
            String conditions = task.getConditions();  //检索式
            String orderBy = task.getOrderBy();  //排序字段
            String orderByType = task.getOrderByType();  //排序类型
            String dbType = task.getDBType();  //检索数据库类型
            List<String> cells = task.getConfigCells();  //下载字段
            Integer startNumber = task.getStartNumber();  //下载起始条数位置
            Integer endNumber = task.getEndNumber();  //下载终止条数位置
            List<String> isAddPatentNos = task.getIsAddPatentNos();  //需要额外下载的专利号
            List<String> isDeletePatentNos = task.getIsDeletePatentNos();  //起止条数中不需要下载的专利号
            //startToEndNum：起止条数中需要下载的专利总数量
            int startToEndNum = 0;
            if (endNumber > 0) {
                startToEndNum = endNumber - startNumber + 1;
                if (isDeletePatentNos != null && isDeletePatentNos.size() > 0) {
                    startToEndNum = startToEndNum - isDeletePatentNos.size();
                }
            }

            //若有完成条数，即表示此次任务为暂停后的继续执行，则将起始条数 startNumber重置为成功条数 + 1
            if (successNum > 0) {
                startNumber = successNum + 1;
            }

            //若有起止条数，并且完成条数在起止条数内（即起止条数的专利还没有下载完）
            if (endNumber > 0 && startNumber <= endNumber && successNum < startToEndNum) {
                Calculate calculate = calculateFromStartAndEndNumber(startNumber, endNumber);
                Integer startPage = calculate.getStartPage();
                Integer startNum = calculate.getStartNum();
                Integer endPage = calculate.getEndPage();
                Integer endNum = calculate.getEndNum();

                //根据计算出的起止页数，一页一页检索
                int pageNum = startPage;
                for (int i = startPage; i <= endPage; i++) {
                    PatentStarListDto patentStarListDto = new PatentStarListDto()
                            .setCurrentQuery(conditions)
                            .setOrderBy(orderBy)
                            .setOrderByType(orderByType)
                            .setPageNum(pageNum++)
                            .setRowCount(50)
                            .setDBType(dbType);
                    //调用一般接口返回一批专利著录相关数据
                    Map<String, Object> resultMap = patentStarApiService.patentStarSearchApi(patentStarListDto);
                    if (resultMap == null || (Integer) resultMap.get("total") == 0) {
                        ThrowException.throwXiaoShiException("未检索到相关专利");
                    }

                    List<StarPatentVO> starPatents = (List<StarPatentVO>) resultMap.get("records");
                    //遍历这一页的专利
                    for (int j = 0; j < starPatents.size(); j++) {
                        //若任务状态为已暂停，则结束生产
                        if (pTaskId.equals(task.getId()) && pTaskStatus == 4) {
                            return;
                        }
                        //若还没到开始页的开始位置，则跳过，不下载它
                        if (i == startPage && j < startNum - 1) {
                            continue;
                        }
                        //若到了结束页的结束位置
                        if (i == endPage && j == endNum) {
                            break;
                        }
                        //若当前遍历到的专利号是需要删除的专利，则跳过，不下载它
                        if (isDeletePatentNos != null && isDeletePatentNos.size() > 0 && isDeletePatentNos.contains(starPatents.get(j).getApplicationNo())) {
                            continue;
                        }

                        UploadParamsVO uploadParamsVO = new UploadParamsVO();
                        Patent patent = new Patent();
                        uploadParamsVO.setPatent(patent);
                        uploadParamsVO.getPatent().setPatentNo(starPatents.get(j).getPatentNo());
                        uploadPatentBatchService.getOneOrInsertOne(uploadParamsVO);

                        PQueueData pQueueData = new PQueueData()
                                .setTask(task)
                                .setStarPatent(starPatents.get(j))
                                .setUploadParamsVO(uploadParamsVO);

                        //专利丢入著录生产者队列，并唤醒著录生产者线程
                        if (cells.contains("1")) {
                            pantentQueueService.zhuluToPQueue(pQueueData);
                        }
                        //专利丢入权要生产者队列，并唤醒权要生产者线程
                        if (cells.contains("2")) {
                            pantentQueueService.rightToPQueue(pQueueData);
                        }
                        //专利丢入说明书文本生产者队列，并唤醒说明书文本生产者线程
                        if (cells.contains("3")) {
                            pantentQueueService.instructionTextToPQueue(pQueueData);
                        }
                        //专利丢入说明书pdf生产者队列，并唤醒说明书pdf生产者线程
                        if (cells.contains("4")) {
                            pantentQueueService.instructionPDFToPQueue(pQueueData);
                        }
                        //专利丢入摘要附图生产者队列，并唤醒摘要附图生产者线程
                        if (cells.contains("6")) {
                            pantentQueueService.imageToPQueue(pQueueData);
                        }

                    }

                }
            }

            //若是暂停后继续的任务，若 successNum > startToEndNum，即上一次已经下载完了起止条数中的专利，还下载了isAdd中的部分专利
            int fromIndex = 0;
            if (successNum > 0 && successNum > startToEndNum) {
                fromIndex = successNum - startToEndNum;
            }
            //下载isAdd中的专利 / 下载多个专利号导入接口的专利 ↓
            if (isAddPatentNos != null && isAddPatentNos.size() > 0) {
                //fromIndex > 0 表示上一次执行的下载已经下载了isAdd中的部分专利，此次需要下载剩余专利
                if (fromIndex > 0) {
                    isAddPatentNos = isAddPatentNos.subList(fromIndex, isAddPatentNos.size() - 1);
                }
                //若是检索页面网站导入，则isAddPatentNos是前台传的多个申请号，即包含"."
                if (isAddPatentNos.get(0).contains(".")) {
                    downLoadIsAddPatentNos(isAddPatentNos, task, orderBy, orderByType, dbType, cells, null);
                } else {
                    //若是多个专利号导入的下载，则isAddPatentNos是多个专利号，不包含"."
                    downLoadIsAddPatentNos(isAddPatentNos, task, orderBy, orderByType, dbType, cells, conditions);
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
            //生产消费到一半时，发生错误异常，将任务状态置为完成
            task = taskService.getById(task.getId());
            if (task.getStatus().equals(1)) {
                task.setStatus(2);
                taskService.updateById(task);
            }
        }
    }

    /**
     * 装载著录方法
     *
     * @param starPatent     专利之星著录对象
     * @param uploadParamsVO 专利实体类对象
     */
    public void setPatentZhuLu(StarPatentVO starPatent, UploadParamsVO uploadParamsVO) {
        //以下 ↓装载的是调用"一般检索"接口返回的专利相关数据
        //Patent patent = new Patent();
        //装载专利号
        uploadParamsVO.getPatent().setPatentNo(starPatent.getPatentNo());
        //装载摘要
        uploadParamsVO.getPatent().setAbstractStr(starPatent.getAbstractStr());
        //装载标题
        uploadParamsVO.getPatent().setName(starPatent.getName());
        //装载申请号
        uploadParamsVO.getPatent().setApplicationNo(starPatent.getApplicationNo());
        //装载申请日
        if (starPatent.getApplicationDate() != null && !starPatent.getApplicationDate().equals("")) {
            int timeStamp = stringDateToTimeStamp(starPatent.getApplicationDate());
            uploadParamsVO.getPatent().setApplicationDate(timeStamp);
        }
        //装载公开号
        uploadParamsVO.getPatent().setPublicNo(starPatent.getPublicNo());
        //装载公开日
        if (starPatent.getPublicDate() != null && !starPatent.getPublicDate().equals("")) {
            int timeStamp = stringDateToTimeStamp(starPatent.getPublicDate());
            uploadParamsVO.getPatent().setPublicDate(timeStamp);
        }
        //装载申请人
        if (starPatent.getApplicantStr() != null && !starPatent.getApplicantStr().equals("")) {
            uploadParamsVO.setPatentApplicantOriginalName(Arrays.asList(starPatent.getApplicantStr().split(";")));
        }
        //装载权利人
        if (starPatent.getCurrentApplicantStr() != null && !starPatent.getCurrentApplicantStr().equals("")) {
            uploadParamsVO.setPatentApplicantCurrentName(Arrays.asList(starPatent.getCurrentApplicantStr().split(";")));
        }
        //装载IPC分类号
        if (starPatent.getIpcListStr() != null && !starPatent.getIpcListStr().equals("")) {
            String[] ipcArr = starPatent.getIpcListStr().split(";");
            //装载主分类号
            uploadParamsVO.setMainIpc(ipcArr[0]);
            uploadParamsVO.setIpcList(Arrays.asList(ipcArr));
        }
        //装载法律状态（os_patent表status字段值）
        Integer status = starPatent.getLG();
        if (status != null) {
            //有效（有权）
            if (status == 1) {
                uploadParamsVO.getPatent().setSimpleStatus(3);
                //失效（无权）
            } else if (status == 2) {
                uploadParamsVO.getPatent().setSimpleStatus(2);
                //审中（审中）
            } else if (status == 3) {
                uploadParamsVO.getPatent().setSimpleStatus(1);
            }
        }
        uploadParamsVO.setPatentSimpleStatus(starPatent.getSimpleStatus());
        uploadParamsVO.setSimpleStatus(starPatent.getSimpleStatus());


        //以下 ↓装载的是调用"获得中国专利著录"接口返回的专利相关数据
        String appNo;
        if (starPatent.getApplicationNo().contains(".")) {
            appNo = starPatent.getApplicationNo().substring(0, starPatent.getApplicationNo().lastIndexOf("."));
        } else {
            appNo = starPatent.getApplicationNo();
        }
        //调用中国专利著录接口返回的专利相关数据最外层是一个集合"[]"，但是集合中只有一个对象"{}"，以下方式处理
        String chinaPatentZhuLuStr = patentStarApiService.getCnBibApi(appNo);
        if (chinaPatentZhuLuStr != null && !chinaPatentZhuLuStr.trim().equals("") && !chinaPatentZhuLuStr.equals("{}")) {
            List<ChinaPatentZhuLu> chinaPatentZhuLus = JSON.parseArray(chinaPatentZhuLuStr, ChinaPatentZhuLu.class);
            ChinaPatentZhuLu chinaPatentZhuLu = chinaPatentZhuLus.get(0);

            //装载申请人地址
            if (chinaPatentZhuLu.getDZ() != null && !chinaPatentZhuLu.getDZ().equals("")) {
                ArrayList<String> patentApplicantOriginalAddresss = new ArrayList<>();
                if (chinaPatentZhuLu.getDZ().contains(" ")) {
                    patentApplicantOriginalAddresss.add(chinaPatentZhuLu.getDZ().substring(chinaPatentZhuLu.getDZ().indexOf(" ") + 1));
                } else {
                    patentApplicantOriginalAddresss.add(chinaPatentZhuLu.getDZ());
                }
                uploadParamsVO.setPatentApplicantOriginalAddress(patentApplicantOriginalAddresss);
            }
            //装载代理人
            if (chinaPatentZhuLu.getAT() != null && !chinaPatentZhuLu.getAT().equals("")) {
                List<String> patentAgents = Arrays.asList(chinaPatentZhuLu.getAT().split(";"));
                ArrayList<PatentAgent> patentAgentList = new ArrayList<>();
                for (String n : patentAgents) {
                    PatentAgent patentAgent = new PatentAgent();
                    patentAgent.setName(n);
                    patentAgentList.add(patentAgent);
                }
                uploadParamsVO.setPatentAgentList(patentAgentList);
            }
            //装载代理机构地址
            if (chinaPatentZhuLu.getAGN() != null && !chinaPatentZhuLu.getAGN().equals("")) {
                String agencyAddress;
                if (chinaPatentZhuLu.getAGN().contains(" ")) {
                    agencyAddress = chinaPatentZhuLu.getAGN().substring(0, chinaPatentZhuLu.getAGN().lastIndexOf(" "));
                } else {
                    agencyAddress = chinaPatentZhuLu.getAGN();
                }
                uploadParamsVO.getPatent().setAgencyId(agencyAddress);
            }
            //装载发明人
            if (chinaPatentZhuLu.getIV() != null && !chinaPatentZhuLu.getIV().equals("")) {
                List<String> patentInventorNames = Arrays.asList(chinaPatentZhuLu.getIV().split(";"));
                ArrayList<PatentInventor> patentInventors = new ArrayList<>();
                for (String patentInventorName : patentInventorNames) {
                    PatentInventor patentInventor = new PatentInventor();
                    patentInventor.setName(patentInventorName);
                    patentInventors.add(patentInventor);
                }
                uploadParamsVO.setPatentInventorList(patentInventors);
            }
            //装载优先权号、优先权国家、优先权日
            uploadParamsVO.getPatent().setPriorityNo(chinaPatentZhuLu.getPR());
        }

        //以下 ↓装载的是调用"获得同族专利"接口返回的专利相关数据
        if (starPatent.getPatentNo() != null && !starPatent.getPatentNo().equals("")) {
            String familyPatentNoStr = patentStarApiService.getFamilyByPubNoApi(starPatent.getPatentNo());
            if (!familyPatentNoStr.equals("no data")) {
                FamilyPatentNo familyPatentNo = JSON.parseObject(familyPatentNoStr, FamilyPatentNo.class);
                //装载同族号
                if (familyPatentNo.getFamilyinfo() != null && !familyPatentNo.getFamilyinfo().equals("")) {
                    List<String> simpleFamily = Arrays.asList(familyPatentNo.getFamilyinfo().split(";"));
                    uploadParamsVO.setSimpleFamily(simpleFamily);
                }
            }
        }

        //以下 ↓装载的是调用"获得中国专利法律状态"接口返回的专利相关数据
        PatentAffair patentAffair = new PatentAffair();
        String cnLegalApiStr = patentStarApiService.getCnLegalApi(appNo);
        List<ChinaLeagalStatus> chinaLeagalStatuses = JSON.parseArray(cnLegalApiStr, ChinaLeagalStatus.class);
        if (chinaLeagalStatuses != null && chinaLeagalStatuses.size() > 0) {
            ArrayList<KeyValueVO> lst = new ArrayList<>();
            HashMap<Integer, String> nameMap = new HashMap<>();
            HashMap<Integer, String> contentMap = new HashMap<>();
            nameMap.put(0, "发生日期");
            nameMap.put(1, "法律状态");
            nameMap.put(2, "详细法律状态");
            nameMap.put(3, "详细信息");
            for (int i = 0; i < chinaLeagalStatuses.size(); i++) {
                if (i == 0) {
                    patentAffair.setStatus(chinaLeagalStatuses.get(i).getLegalStatus());
                }
                contentMap.put(0, chinaLeagalStatuses.get(i).getLegalDate());
                contentMap.put(1, chinaLeagalStatuses.get(i).getLegalStatus());
                contentMap.put(2, chinaLeagalStatuses.get(i).getLegalStatusInfo());
                contentMap.put(3, chinaLeagalStatuses.get(i).getDETAIL());
                ArrayList<KeyValueVO.InpadocData> inpadocDatas = new ArrayList<>();
                for (int j = 0; j < 4; j++) {
                    KeyValueVO.InpadocData inpadocData = new KeyValueVO.InpadocData();
                    inpadocData.setName(nameMap.get(j));
                    inpadocData.setContent(contentMap.get(j));
                    inpadocDatas.add(inpadocData);
                }
                KeyValueVO keyValueVO = new KeyValueVO();
                keyValueVO.setInpadocData(inpadocDatas);
                lst.add(keyValueVO);
            }
            //装载事务表的status（公开|授权|驳回|权力转移。。。）
            String content = JSONObject.toJSONString(lst);
            patentAffair.setContent(content);
            uploadParamsVO.setPatentAffair(patentAffair);
        }


    }

    /**
     * 装载权要方法
     *
     * @param starPatent     专利之星著录对象
     * @param uploadParamsVO 专利实体类对象
     */
    public void setPatentClaim(StarPatentVO starPatent, UploadParamsVO uploadParamsVO) {
        try {
            String appNo;
            if (starPatent.getApplicationNo().contains(".")) {
                appNo = starPatent.getApplicationNo().substring(0, starPatent.getApplicationNo().lastIndexOf("."));
            } else {
                appNo = starPatent.getApplicationNo();
            }
            //根据申请号调用"获得中国专利全文文本"接口，获得包含各种xml标签的专利全文内容的长字符串 cnFullXmlStr
            String cnFullXmlStr = patentStarApiService.getCnFullXmlApi(appNo);

            //使用正则表达式拼接出权要原文
            String regex = "(?<=<claim id=.{1,110}>)[\\w\\W]+?(?=</claim>)";
            Pattern compile = Pattern.compile(regex);
            Matcher matcher = compile.matcher(cnFullXmlStr);
            StringBuilder builder = new StringBuilder();
            while (matcher.find()) {
                String macherGroup = matcher.group();
                String right = macherGroup.replaceAll("<.*?>", "").trim();
                builder.append(right).append("\r\n");
            }

            String patentRightText = builder + "";

            //使用工具类去除字符串文本中的所有HTML格式标签
            patentRightText = RemoveHtmlTagsUtils.removeHtmlTags(patentRightText);
            patentRightText = patentRightText.trim();

            //装载权利要求原文
            PatentRight patentRight = new PatentRight();
            patentRight.setContent(patentRightText);
            uploadParamsVO.setPatentRight(patentRight);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 装载说明书文本
     *
     * @param starPatent     专利之星著录对象
     * @param uploadParamsVO 专利实体类对象
     */
    public void setPatentInstructionText(StarPatentVO starPatent, UploadParamsVO uploadParamsVO) {
        try {
            String appNo;
            if (starPatent.getApplicationNo().contains(".")) {
                appNo = starPatent.getApplicationNo().substring(0, starPatent.getApplicationNo().lastIndexOf("."));
            } else {
                appNo = starPatent.getApplicationNo();
            }
            //根据申请号调用"获得中国专利全文文本"接口，获得包含各种xml标签的专利全文内容的长字符串 cnFullXmlStr
            String cnFullXmlStr = patentStarApiService.getCnFullXmlApi(appNo);

            //使用正则表达式拼接出说明书文本全文
            String regex = "(?<=<p id=\"p)[\\w\\W]+?(?=</p>)";
            Pattern compile = Pattern.compile(regex);
            Matcher matcher = compile.matcher(cnFullXmlStr);
            StringBuilder builder = new StringBuilder();
            while (matcher.find()) {
                String oldRow = matcher.group();
                if (oldRow.contains("num=\"n")) {
                    oldRow = oldRow.substring(oldRow.indexOf("num=\"n") + 6);
                    oldRow = "[" + oldRow;
                    oldRow = oldRow.replace("\">", "]");
                } else if (oldRow.contains("num=")) {
                    oldRow = oldRow.substring(oldRow.indexOf("num=") + 5);
                    oldRow = "[" + oldRow;
                    oldRow = oldRow.replace("\">", "]");
                } else {
                    oldRow = oldRow.substring(oldRow.indexOf("\">") + 2);
                }
                builder.append(oldRow).append("\r\n");
            }

            String instructionText = builder + "";

            //使用工具类去除字符串文本中的所有HTML格式标签
            instructionText = RemoveHtmlTagsUtils.removeHtmlTags(instructionText);
            instructionText = instructionText.trim();

            //装载说明书文本全文
            PatentInstructionText patentInstructionText = new PatentInstructionText();
            patentInstructionText.setManual(instructionText);
            uploadParamsVO.setPatentInstructionText(patentInstructionText);

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 装载说明书pdf
     *
     * @param starPatent     专利之星著录对象
     * @param uploadParamsVO 专利实体类对象
     */
    public void setPatentInstructionPDF(StarPatentVO starPatent, UploadParamsVO uploadParamsVO) {
        try {
            //根据专利号调用"获得世界专利pdf"接口，获得pdf的url地址
            if (starPatent.getPatentNo() != null && !starPatent.getPatentNo().equals("")) {
                String pdfUrl = patentStarApiService.getEnPdfApi(starPatent.getPatentNo());
                URL url = new URL(pdfUrl);  //想要读取的url地址
                InputStream in = url.openStream();

                File file = File.createTempFile("new_url", ".pdf");  //创建文件
                OutputStream os = new FileOutputStream(file);  //创建文件输出流
                int bytesRead;
                byte[] buffer = new byte[8192];
                int len = 8192;
                while ((bytesRead = in.read(buffer, 0, len)) != -1) {
                    os.write(buffer, 0, bytesRead);
                }
                //关闭释放流
                os.close();
                in.close();

                DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(16, null);
                FileItem item = diskFileItemFactory.createItem(file.getName(), "text/plain", true, file.getName());
                buffer = new byte[8192];
                FileInputStream fis = new FileInputStream(file);
                OutputStream fos = item.getOutputStream();
                len = 8192;
                while ((bytesRead = fis.read(buffer, 0, len)) != -1) {
                    fos.write(buffer, 0, bytesRead);
                }
                //关闭释放流
                fos.close();
                fis.close();
                MultipartFile multipartFile = new CommonsMultipartFile(item);
                UploadFileDTO fileDTO = fileUtils.uploadFile(multipartFile);
                uploadParamsVO.setFileDTO(fileDTO);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 装载摘要附图
     *
     * @param starPatent     专利之星著录对象
     * @param uploadParamsVO 专利实体类对象
     */
    public void setPatentPicture(StarPatentVO starPatent, UploadParamsVO uploadParamsVO) {
        //取出一般接口返回的摘要附图路径
        String pictureUrl = starPatent.getAbstractPath();

        try {
            URL url = new URL(pictureUrl);  //想要读取的url地址
            InputStream in = url.openStream();

            File file = File.createTempFile("new_url", ".jpg");  //创建文件
            OutputStream os = new FileOutputStream(file);  //创建文件输出流
            int bytesRead;
            byte[] buffer = new byte[8192];
            int len = 8192;
            while ((bytesRead = in.read(buffer, 0, len)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            //关闭释放流
            os.close();
            in.close();

            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory(16, null);
            FileItem item = diskFileItemFactory.createItem(file.getName(), "text/plain", true, file.getName());
            buffer = new byte[8192];
            FileInputStream fis = new FileInputStream(file);
            OutputStream fos = item.getOutputStream();
            len = 8192;
            while ((bytesRead = fis.read(buffer, 0, len)) != -1) {
                fos.write(buffer, 0, bytesRead);
            }
            //关闭释放流
            fos.close();
            fis.close();
            MultipartFile multipartFile = new CommonsMultipartFile(item);
            UploadFileDTO fileDTO = fileUtils.uploadFile(multipartFile);
            uploadParamsVO.setFileDTO(fileDTO);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 下载指定多个专利号专利
     *
     * @param isAddPatentNos 起止条数以外，用户手动勾选的多个专利号
     */
    public void downLoadIsAddPatentNos(List<String> isAddPatentNos, Task task, String orderBy, String orderByType, String dbType, List<String> cells, String conditions) throws IOException {
        if (conditions == null) {
            conditions = "(AN=(" + StringUtils.join(isAddPatentNos, " OR ") + "))";
        }

        int pageNum = 1;
        for (int i = 0; i < isAddPatentNos.size(); i += 50) {
            PatentStarListDto patentStarListDto = new PatentStarListDto()
                    .setCurrentQuery(conditions)
                    .setOrderBy(orderBy)
                    .setOrderByType(orderByType)
                    .setPageNum(pageNum++)
                    .setRowCount(50)
                    .setDBType(dbType);
            Map<String, Object> resultMap = patentStarApiService.patentStarSearchApi(patentStarListDto);
            if (resultMap == null || (Integer) resultMap.get("total") == 0) {
                ThrowException.throwXiaoShiException("发生未知错误，一般接口未检索出专利");
            }

            List<StarPatentVO> starPatents = (List<StarPatentVO>) resultMap.get("records");
            //遍历这一页的专利
            for (StarPatentVO starPatent : starPatents) {
                //判断若任务状态为已暂停，则结束生产
                if (pTaskId.equals(task.getId()) && pTaskStatus == 4) {
                    return;
                }
                try {
                    UploadParamsVO uploadParamsVO = new UploadParamsVO();
                    Patent patent = new Patent();
                    uploadParamsVO.setPatent(patent);
                    uploadParamsVO.getPatent().setPatentNo(starPatent.getPatentNo());
                    uploadPatentBatchService.getOneOrInsertOne(uploadParamsVO);

                    PQueueData pQueueData = new PQueueData()
                            .setTask(task)
                            .setStarPatent(starPatent)
                            .setUploadParamsVO(uploadParamsVO);
                    //装载专利著录
                    if (cells.contains("1")) {
                        pantentQueueService.zhuluToPQueue(pQueueData);
                    }
                    //装载权要
                    if (cells.contains("2")) {
                        pantentQueueService.rightToPQueue(pQueueData);
                    }
                    //装载说明书文本
                    if (cells.contains("3")) {
                        pantentQueueService.instructionTextToPQueue(pQueueData);
                    }
                    //装载说明书pdf
                    if (cells.contains("4")) {
                        pantentQueueService.instructionPDFToPQueue(pQueueData);
                    }
                    //装载摘要附图
                    if (cells.contains("6")) {
                        pantentQueueService.imageToPQueue(pQueueData);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }

    }

    /**
     * 专利之星返回日期格式为字符串 yyyyMMdd，如 "20230713"，本方法将其转成10位数字时间戳
     *
     * @param dateStr yyyyMMdd格式字符串日期
     * @return 返回10位数字时间戳
     */
    public int stringDateToTimeStamp(String dateStr) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        Date date;
        try {
            date = dateFormat.parse(dateStr);
        } catch (ParseException e) {
            //日期格式转换异常
            e.printStackTrace();
            return Integer.parseInt(dateStr);
        }
        long timeStamp = date.getTime() / 1000;
        return (int) timeStamp;
    }

    /**
     * 根据起止条数计算开始页数、开始页数的开始位置、结束页数、结束页数的结束位置
     *
     * @param startNumber 起始条数
     * @param endNumber   终止条数
     * @return 返回计算结果对象（开始页数、开始页数的开始位置、结束页数、结束页数的结束位置）
     */
    public Calculate calculateFromStartAndEndNumber(Integer startNumber, Integer endNumber) {
        int startPage;  //检索开始页数
        int startNum;  //检索开始页数的开始专利位置
        int endPage;  //检索结束页数
        int endNum;  //检索结束页数的结束专利位置
        if (startNumber % 50 != 0) {
            startPage = startNumber / 50 + 1;
            startNum = startNumber % 50;
        } else {
            startPage = startNumber / 50;
            startNum = 50;
        }
        if (endNumber % 50 != 0) {
            endPage = endNumber / 50 + 1;
            endNum = endNumber % 50;
        } else {
            endPage = endNumber / 50;
            endNum = 50;
        }

        Calculate calculate = new Calculate()
                .setStartPage(startPage)
                .setStartNum(startNum)
                .setEndPage(endPage)
                .setEndNum(endNum);

        return calculate;
    }

    public void setTaskStatus(Integer taskId, Integer taskStatus) {
        this.pTaskId = taskId;
        this.pTaskStatus = taskStatus;
    }

    public Integer getpTaskId() {
        return pTaskId;
    }

    public Integer getpTaskStatus() {
        return pTaskStatus;
    }


}
