package cn.cslg.pas.service.getPatentStarPart;

import cn.cslg.pas.common.model.dto.GetPatentStarPartDTO;
import cn.cslg.pas.common.model.dto.PatentDTO;
import cn.cslg.pas.common.model.outApi.PatentStarListDto;
import cn.cslg.pas.common.model.vo.KeyValueVO;
import cn.cslg.pas.common.model.vo.PageVO;
import cn.cslg.pas.common.model.vo.UploadParamsVO;
import cn.cslg.pas.common.model.vo.outApi.StarPatentVO;
import cn.cslg.pas.common.utils.ThrowException;
import cn.cslg.pas.domain.*;
import cn.cslg.pas.service.outApi.PatentStarApiService;
import cn.cslg.pas.service.upLoadPatent.ExcutePatentDataStar;
import com.alibaba.fastjson.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

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

/**
 * 获取专利之星专利某部分（如权要、说明书等一项）业务层
 *
 * @Author chenyu
 * @Date 2023/6/30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GetPatentStarPartService {
    private final ExcutePatentDataStar excutePatentDataStar;
    private final PatentStarApiService patentStarApiService;

    /**
     * 根据专利号或申请号获取专利指定部分项
     *
     * @param getPatentStarPartDTO 前端传输DTO对象
     * @return 返回装载着指定专利项的对象
     */
    public PatentDTO getPatentPart(GetPatentStarPartDTO getPatentStarPartDTO) throws IOException {
        log.info("开始处理【根据专利号或申请号获取专利指定部分项】的业务，参数为：{}", getPatentStarPartDTO);

        Integer patentCell = getPatentStarPartDTO.getPatentCell();
        String appNo = getPatentStarPartDTO.getAppNo();
        String patentNo = getPatentStarPartDTO.getPatentNo();
        PatentDTO patentDTO;
        if (patentCell == 1) {
            patentDTO = getParentRight(appNo);  //拿权要
        } else if (patentCell == 2) {
            patentDTO = getInstructionText(appNo);  //拿说明书文本
        } else if (patentCell == 3) {
            patentDTO = getInstructionPDF(patentNo);  //拿说明书pdf
        } else if (patentCell == 4) {
            patentDTO = getPatentImage(appNo);  //拿摘要附图
        } else if (patentCell == 5) {
            patentDTO = getSimpleFamily(getPatentStarPartDTO);  //拿同族专利信息
        } else if (patentCell == 6) {
            patentDTO = getAffair(appNo);  //拿法律事务信息
        } else {
            patentDTO = new PatentDTO();
        }

        return patentDTO;
    }

    /**
     * 获取专利之星专利的权要
     *
     * @param appNo 申请号
     * @return 返回装载着权要的对象
     */
    public PatentDTO getParentRight(String appNo) {
        StarPatentVO starPatentVO = new StarPatentVO()
                .setApplicationNo(appNo);
        UploadParamsVO uploadParamsVO = new UploadParamsVO();
        //调用"获得中国专利全文文本"接口，处理xml格式权要
        excutePatentDataStar.setPatentClaim(starPatentVO, uploadParamsVO);

        PatentDTO patentDTO = new PatentDTO();
        ArrayList<PatentRight> patentRights = new ArrayList<>();
        patentRights.add(uploadParamsVO.getPatentRight());
        patentDTO.setRights(patentRights);

        return patentDTO;
    }

    /**
     * 获取专利之星专利的说明书文本
     *
     * @param appNo 申请号
     * @return 返回装载着说明书文本的对象
     */
    public PatentDTO getInstructionText(String appNo) {
        StarPatentVO starPatentVO = new StarPatentVO()
                .setApplicationNo(appNo);
        UploadParamsVO uploadParamsVO = new UploadParamsVO();
        //调用"获得中国专利全文文本"接口，处理xml格式说明书文本
        excutePatentDataStar.setPatentInstructionText(starPatentVO, uploadParamsVO);

        PatentDTO patentDTO = new PatentDTO();
        patentDTO.setInstruction(uploadParamsVO.getPatentInstructionText());

        return patentDTO;
    }

    /**
     * 获取专利之星专利的说明书pdf
     *
     * @param patentNo 专利号（公开号）
     * @return 返回装载着说明书pdf的对象
     */
    public PatentDTO getInstructionPDF(String patentNo) {
        //调用"获得世界专利pdf"接口，获得pdf的url地址
        String pdfUrl = patentStarApiService.getEnPdfApi(patentNo);

        PatentDTO patentDTO = new PatentDTO();
        ArrayList<PatentInstruction> patentInstructions = new ArrayList<>();
        PatentInstruction patentInstruction = new PatentInstruction();
        patentInstruction.setUrl(pdfUrl);
        patentInstructions.add(patentInstruction);
        patentDTO.setPdf(patentInstructions);

        return patentDTO;
    }

    /**
     * 获取专利之星专利的摘要附图
     *
     * @param appNo 申请号
     * @return 返回装载着摘要附图的对象
     */
    public PatentDTO getPatentImage(String appNo) {
        //以下 ↓调用的是"获得中国专利摘要附图"接口，获得摘要附图的url地址
        if (appNo.contains(".")) {
            appNo = appNo.substring(0, appNo.lastIndexOf("."));
        }
        String pictureUrl = patentStarApiService.getPictureApi(appNo);

        PatentDTO patentDTO = new PatentDTO();
        ArrayList<PatentImage> patentImages = new ArrayList<>();
        PatentImage patentImage = new PatentImage();
        patentImage.setUrl(pictureUrl);
        patentImages.add(patentImage);
        patentDTO.setImage(patentImages);

        return patentDTO;
    }

    /**
     * 获取专利之星专利的同族专利
     *
     * @param getPatentStarPartDTO 获取专利之星专利指定项DTO类
     * @return 返回装载着同族专利的对象集合
     */
    public PatentDTO getSimpleFamily(GetPatentStarPartDTO getPatentStarPartDTO) throws IOException {
        //从DTO中取出公开号、当前页、每页条数
        String patentNo = getPatentStarPartDTO.getPatentNo();
        Integer current = getPatentStarPartDTO.getCurrent();
        Integer size = getPatentStarPartDTO.getSize();

        PatentDTO patentDTO = new PatentDTO();
        PageVO pageVO = new PageVO()
                .setCurrent(current)
                .setSize(size);

        //以下 ↓装载的是调用"获得同族专利"接口返回的专利相关数据
        String familyPatentNoStr = patentStarApiService.getFamilyByPubNoApi(patentNo);
        //若没有同族号，则返回空集合（表示该公开号暂无同族）
        if (familyPatentNoStr.equals("no data")) {
            pageVO.setRecords(new ArrayList<>())
                    .setTotal(0);
            patentDTO.setFamilyPatentResult(pageVO);
            return patentDTO;
        }

        FamilyPatentNo familyPatentNo = JSON.parseObject(familyPatentNoStr, FamilyPatentNo.class);
        //familyPNStr：以分号;拼接的多个同族公开号字符串
        String familyPNStr = familyPatentNo.getFamilyinfo();
        List<String> familyPatentNos = Arrays.asList(familyPNStr.split(";"));

        //防止下标越界的判断（即判断所需当前页是否有数据）
        if ((current - 1) * size >= familyPatentNos.size()) {
            pageVO.setRecords(new ArrayList<>())
                    .setTotal(familyPatentNos.size());
            patentDTO.setFamilyPatentResult(pageVO);
            return patentDTO;
        }

        //根据分页信息，取分页区间内的同族号
        familyPatentNos = pageBySubList(familyPatentNos, current, size);
        //集合转成字符串
        String conditions = "(PN=(" + StringUtils.join(familyPatentNos, " OR ") + "))";

        //调用一般接口返回这些同族号专利的著录相关数据（标题、申请人、权利人、摘要附图）
        PatentStarListDto patentStarListDto = new PatentStarListDto()
                .setCurrentQuery(conditions)
                .setOrderBy("ID")
                .setOrderByType("DESC")
                .setPageNum(current)
                .setRowCount(size)
                .setDBType("WD");
        Map<String, Object> resultMap = patentStarApiService.patentStarSearchApi(patentStarListDto);
        if (resultMap == null || (Integer) resultMap.get("total") == 0) {
            ThrowException.throwXiaoShiException("发生未知错误，一般接口未检索出专利");
        }

        List<StarPatentVO> patents = (List<StarPatentVO>) resultMap.get("records");
        List<PatentSimpleFamilyLink> records = new ArrayList<>();
        for (StarPatentVO starPatent : patents) {
            PatentSimpleFamilyLink patentSimpleFamilyLink = new PatentSimpleFamilyLink();
            patentSimpleFamilyLink.setAbstractPath(starPatent.getAbstractPath());  //装载摘要附图
            patentSimpleFamilyLink.setPatentNo(starPatent.getPatentNo());  //装载公开号
            patentSimpleFamilyLink.setName(starPatent.getName());  //装载标题
            //装载申请人和权利人
            ArrayList<PatentApplicant> patentApplicants = new ArrayList<>();
            List<String> applicantNames = Arrays.asList(starPatent.getApplicantStr().split(";"));
            for (String applicantName : applicantNames) {
                PatentApplicant patentApplicant = new PatentApplicant();
                patentApplicant.setName(applicantName);
                patentApplicant.setDataType(1);
                patentApplicants.add(patentApplicant);  //装载申请人
                patentApplicant.setDataType(2);
                patentApplicants.add(patentApplicant);  //装载权利人
            }
            patentSimpleFamilyLink.setApplicant(patentApplicants);
            records.add(patentSimpleFamilyLink);
        }
        pageVO.setRecords(records)
                .setTotal(familyPatentNos.size());
        patentDTO.setFamilyPatentResult(pageVO);
        return patentDTO;
    }

    public PatentDTO getAffair(String appNo) throws IOException {
        if (appNo.contains(".")) {
            appNo = appNo.substring(0, appNo.lastIndexOf("."));
        }
        //以下 ↓装载的是调用"获得中国专利法律状态"接口返回的专利相关数据
        String cnLegalApiStr = patentStarApiService.getCnLegalApi(appNo);
        List<ChinaLeagalStatus> chinaLeagalStatuses = JSON.parseArray(cnLegalApiStr, ChinaLeagalStatus.class);
        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 (ChinaLeagalStatus chinaLeagalStatus : chinaLeagalStatuses) {
            contentMap.put(0, chinaLeagalStatus.getLegalDate());
            contentMap.put(1, chinaLeagalStatus.getLegalStatus());
            contentMap.put(2, chinaLeagalStatus.getLegalStatusInfo());
            contentMap.put(3, chinaLeagalStatus.getDETAIL());
            ArrayList<KeyValueVO.InpadocData> inpadocDatas = new ArrayList<>();
            for (int i = 0; i < 4; i++) {
                KeyValueVO.InpadocData inpadocData = new KeyValueVO.InpadocData();
                inpadocData.setName(nameMap.get(i));
                inpadocData.setContent(contentMap.get(i));
                inpadocDatas.add(inpadocData);
            }
            KeyValueVO keyValueVO = new KeyValueVO();
            keyValueVO.setInpadocData(inpadocDatas);
            lst.add(keyValueVO);
        }
        PatentDTO patentDTO = new PatentDTO();
        ArrayList<PatentAffair> patentAffairs = new ArrayList<>();
        PatentAffair patentAffair = new PatentAffair();
        patentAffair.setInpadoc(lst);
        patentAffairs.add(patentAffair);
        patentDTO.setAffair(patentAffairs);
        return patentDTO;
    }


    /**
     * 根据分页信息，取同族号集合中分页区间内的同族号
     *
     * @param list    同族号集合
     * @param current 当前页
     * @param size    每页条数
     * @return 返回需要的同族号集合
     */
    public static List<String> pageBySubList(List<String> list, int current, int size) {
        int totalcount = list.size();
        int pagecount = 0;
        List<String> subList;

        int m = totalcount % size;
        if (m > 0) {
            pagecount = totalcount / size + 1;
        } else {
            pagecount = totalcount / size;
        }

        if (m == 0) {
            subList = list.subList((current - 1) * size, size * (current));
        } else {
            if (current == pagecount) {
                subList = list.subList((current - 1) * size, totalcount);
            } else {
                subList = list.subList((current - 1) * size, size * (current));
            }
        }

        return subList;

    }

}
