package cn.cslg.pas.service.upLoadPatent;

import cn.cslg.pas.common.model.PersonnelVO;
import cn.cslg.pas.common.model.dto.TaskAddNewDTO;
import cn.cslg.pas.common.model.dto.UploadFileDTO;
import cn.cslg.pas.common.model.outApi.PatentStarListDto;
import cn.cslg.pas.common.utils.*;
import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.pas.domain.*;
import cn.cslg.pas.domain.asso.TaskCondition;
import cn.cslg.pas.service.*;
import cn.cslg.pas.service.asso.TaskConditionService;
import cn.cslg.pas.service.outApi.PatentStarApiService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

/**
 * 导入专利任务的业务层
 *
 * @Author 李仁杰
 * 导入任务类
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class UploadTaskService {
    private final FileUtils fileUtils;
    private final TaskService taskService;
    private final PantentQueueService pantentQueueService;
    private final TaskConditionService taskConditionService;
    private final ExcutePatentDataEpo excutePatentDataEpo;
    private final CacheUtils cacheUtils;
    private final LoginUtils loginUtils;
    private final WebLoginConfigService webLoginConfigService;
    private final PatentStarApiService patentStarApiService;
    private final ProjectService projectService;
    private final PatentService patentService;

    /**
     * 新增Excel导入任务
     *
     * @param file Excel文件
     * @param json 前台参数（与专题库关联信息、自定义字段、文件夹等）
     */
    public void addExcelTask(MultipartFile file, String json) throws IOException {
        //将包含多件专利的Excel文件上传至本地，并返回文件对象fileDTO
        UploadFileDTO fileDTO = fileUtils.uploadFile(file);
        //获得文件路径（绝对路径）
        String filePath = fileUtils.getPath(fileDTO.getPath());
        //检查文件合法性并获取专利总数量
        Integer total = ReadExcelUtils.textExcel(filePath);
        //新增任务（专利导入导出任务表）
        Integer taskId = taskService.addTask2(fileDTO, total, json);
        //任务存入生产者任务队列并唤醒生产者线程
        pantentQueueService.taskQueueListAddTask(Arrays.asList(taskId));
        pantentQueueService.awakeTasktch();
    }

    /**
     * 新增专利之星导入任务
     *
     * @param taskAddNewDTO 前台参数（检索信息conditions、专题库id、下载字段configCells等）
     */
    public TaskCondition addPatentStarTask(TaskAddNewDTO taskAddNewDTO) throws IOException {
        log.info("开始处理【新增专利之星下载接口导入专利】的业务，参数为：{}", taskAddNewDTO);

        //检查任务合法性1（检查要导入的专题库或报告是否存在）
        if (taskAddNewDTO.getProjectId() != null) {
            Project project = projectService.getById(taskAddNewDTO.getProjectId());
            if (project == null) {
                ThrowException.throwXiaoShiException("该专题库已不存在，请尝试刷新页面");
            }
        }

        //检查任务合法性2（根据网站配置id和登陆人所属租户id，看是否有网站导入任务的权限）
        Integer webId = taskAddNewDTO.getConfigId();
        PersonnelVO personnelVO = cacheUtils.getLoginUserPersonnel(loginUtils.getId());  //获取登陆人信息
        WebLoginConfig webLoginConfig = webLoginConfigService.getLoginConfig(webId, personnelVO.getTenantId());  //根据网站id获得配置
        if (webLoginConfig == null) {
            ThrowException.throwXiaoShiException("未配置网站登录信息");
        }

        //检查任务合法性3（根据检索式信息调用一般检索接口，看是否能检索出专利）
        PatentStarListDto patentStarListDto = new PatentStarListDto()
                .setCurrentQuery(taskAddNewDTO.getConditions())
                .setOrderBy(taskAddNewDTO.getOrderBy())
                .setOrderByType(taskAddNewDTO.getOrderByType())
                .setPageNum(1)
                .setRowCount(10)
                .setDBType(taskAddNewDTO.getDBType());
        Map<String, Object> resultMap = patentStarApiService.patentStarSearchApi(patentStarListDto);
        if (resultMap == null || (Integer) resultMap.get("total") == 0) {
            ThrowException.throwXiaoShiException("未检索到相关专利");
        }


        //获取专利总数量
        Integer total;
        if (taskAddNewDTO.getEndNumber() > 0) {
            total = taskAddNewDTO.getEndNumber() - taskAddNewDTO.getStartNumber() + 1;
            if (taskAddNewDTO.getIsDeletePatentNos() != null) {
                total = total - taskAddNewDTO.getIsDeletePatentNos().size();
            }
            if (taskAddNewDTO.getIsAddPatentNos() != null) {
                total = total + taskAddNewDTO.getIsAddPatentNos().size();
            }
        } else {
            total = taskAddNewDTO.getIsAddPatentNos().size();
        }

        //新增任务与任务条件关联表（"asso_osTask_qrtzTask"）数据
        TaskCondition taskCondition = new TaskCondition();
        taskCondition
                .setTaskType(taskAddNewDTO.getTaskType())
                .setTaskType2(taskAddNewDTO.getTaskType2())
                .setConditions(taskAddNewDTO.getConditions())
                .setCrons(taskAddNewDTO.getCrons())
                .setConfigId(taskAddNewDTO.getConfigId())
                .setTaskName(taskAddNewDTO.getTaskName())
                .setTotal(total)
                .setOrderBy(taskAddNewDTO.getOrderBy())
                .setOrderByType(taskAddNewDTO.getOrderByType())
                .setDBType(taskAddNewDTO.getDBType())
                .setStartNumber(taskAddNewDTO.getStartNumber())
                .setEndNumber(taskAddNewDTO.getEndNumber());
        if (taskAddNewDTO.getIsAddPatentNos() != null && taskAddNewDTO.getIsAddPatentNos().size() > 0) {
            taskCondition.setIsAddPatentNos(StringUtils.join(taskAddNewDTO.getIsAddPatentNos(), ","));
        }
        if (taskAddNewDTO.getIsDeletePatentNos() != null && taskAddNewDTO.getIsDeletePatentNos().size() > 0) {
            taskCondition.setIsDeletePatentNos(StringUtils.join(taskAddNewDTO.getIsDeletePatentNos(), ","));
        }
        List<String> cells = taskAddNewDTO.getConfigCells();
        if (cells == null) {
            taskCondition.setConfigCells("");
        } else {
            taskCondition.setConfigCells(String.join(",", cells));
        }
        log.info("任务与任务条件关联表（asso_osTask_qrtzTask）新增数据");
        taskConditionService.save(taskCondition);

        //任务表新增任务
        Integer taskId = taskService.addTask3(taskAddNewDTO, total, taskCondition);

        //任务与任务条件关联表（asso_osTask_qrtzTask）更新数据（普通任务）
        if (taskAddNewDTO.getTaskType().equals(0)) {
            taskCondition.setTaskId(taskId);
            taskConditionService.updateById(taskCondition);
        }

        //任务存入生产者任务队列并唤醒生产者线程
        pantentQueueService.taskQueueListAddTask(Arrays.asList(taskId));
        pantentQueueService.awakeTasktch();

        return taskCondition;
    }

    /**
     * 新增Epo网站导入任务
     *
     * @param taskAddNewDTO 前台参数（检索信息conditions、专题库id、下载字段configCells等）
     */
    public TaskCondition addEpoTask(TaskAddNewDTO taskAddNewDTO) throws IOException {
        Integer webId = taskAddNewDTO.getConfigId();
        PersonnelVO personnelVO = cacheUtils.getLoginUserPersonnel(loginUtils.getId());
        //根据网站id获得配置
        WebLoginConfig webLoginConfig = webLoginConfigService.getLoginConfig(webId, personnelVO.getTenantId());
        if (webLoginConfig == null) {
            ThrowException.throwXiaoShiException("未配置网站登录信息");
        }

        //检查任务合法性（检查当前检索式能否检索出专利）
        //根据检索式conditions检索一件专利著录信息
        SerachBiblioData serachBiblioData = excutePatentDataEpo.getSerachBiblioData(taskAddNewDTO.getConditions(), 1, 1);
        if (serachBiblioData == null || serachBiblioData.getTotals() == 0) {
            ThrowException.throwXiaoShiException("根据检索信息未检索到相关专利，请尝试更换检索信息");
        }
        //任务与任务条件关联表新增数据
        TaskCondition taskCondition = new TaskCondition();
        taskCondition
                .setTaskType(taskAddNewDTO.getTaskType())
                .setConditions(taskAddNewDTO.getConditions())
                .setCrons(taskAddNewDTO.getCrons())
                .setConfigId(taskAddNewDTO.getConfigId())
                .setTaskName(taskAddNewDTO.getTaskName())
                .setTotal(serachBiblioData.getTotals());
        List<String> cells = taskAddNewDTO.getConfigCells();
        if (cells == null) {
            taskCondition.setConfigCells("");
        } else {
            taskCondition.setConfigCells(String.join(",", cells));
        }
        taskConditionService.save(taskCondition);

        //任务表新增任务
        Integer taskId = taskService.addTask3(taskAddNewDTO, serachBiblioData.getTotals(), taskCondition);

        //任务与任务条件关联表更新数据
        taskCondition.setTaskId(taskId);
        taskConditionService.updateById(taskCondition);

        //任务存入生产者任务队列并唤醒生产者线程
        pantentQueueService.taskQueueListAddTask(Arrays.asList(taskId));
        pantentQueueService.awakeTasktch();

        return taskCondition;
    }

    public void addPatentNoTask(TaskAddNewDTO taskAddNewDTO) throws IOException {
        log.info("开始处理【根据专利号导入专利任务】的业务，参数为：{}", taskAddNewDTO);

        //检查合法性
        if (taskAddNewDTO == null || taskAddNewDTO.getConditions() == null || taskAddNewDTO.getConditions().trim().equals("")) {
            ThrowException.throwXiaoShiException("请输入专利号");
            return;
        }

        String isAddPatentNosStr = taskAddNewDTO.getConditions();

        //根据专利号生成检索式
        String condition = this.setPatentNosToCondition(taskAddNewDTO.getConditions());
        if (condition == null) {
            ThrowException.throwXiaoShiException("尝试导入的专利号在本系统中均已存在");
        }

        taskAddNewDTO
                .setProjectId(taskAddNewDTO.getProjectId())
                .setReportId(taskAddNewDTO.getReportId())
                .setConditions(condition)
                .setEndNumber(0)
                .setIsAddPatentNos(Arrays.asList(isAddPatentNosStr.split("[,|，]")))
                .setDBType("CN")
                .setOrderBy("ID")
                .setOrderByType("DESC")
                .setConfigCells(Arrays.asList("1", "2", "3", "4", "6"))
                .setConfigId(2)
                .setTaskName("多个专利号导入方式任务")
                .setTaskType(0)
                .setTaskType2(4);

        //根据下载的网站类型新增任务
        if (taskAddNewDTO.getTaskType2().equals(3)) {
            this.addEpoTask(taskAddNewDTO);
        } else if (taskAddNewDTO.getTaskType2().equals(4)) {
            this.addPatentStarTask(taskAddNewDTO);
        }


    }

    public String setPatentNosToCondition(String patentNosStr) {
        String[] patentNo = patentNosStr.split("[,|，]");
        List<String> patentNos = Arrays.asList(patentNo);
        //判断若用户输入的多个专利号字符长度超过了一个专利号长度，而拆分后专利号集合只有一个元素，则定义为用户输入的格式不正确
        if (patentNosStr.length() > 24 && patentNos.size() == 1) {
            ThrowException.throwXiaoShiException("请按照格式要求正确输入专利号（注意：不允许出现空格）");
        }
        //根据专利号从本数据库中查找专利
        LambdaQueryWrapper<Patent> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Patent::getPatentNo, patentNos);
        Function<Object, String> f = (o -> o.toString());
        List<String> dbPatentNos = patentService.listObjs(queryWrapper, f);
        //去除所有查到的专利，若没有剩余则表示要检索的这批专利在本系统数据库中都已存在
        patentNos.removeAll(dbPatentNos);
        if (patentNos.size() == 0) {
            return null;
        }
        //将本系统不包含的专利拼接成条件
        String patentNoCondition = StringUtils.join(patentNos, " OR ");
        String conditions = "PN=(" + patentNoCondition + ") OR GN=(" + patentNoCondition + ")";
        return conditions;
    }

}
