package cn.cslg.pas.service;

import cn.cslg.pas.common.model.dto.CustomFieldLabelDTO;
import cn.cslg.pas.common.model.dto.LabelDTO;
import cn.cslg.pas.common.utils.SecurityUtils.LoginUtils;
import cn.cslg.pas.common.utils.StringUtils;
import cn.cslg.pas.domain.*;
import cn.cslg.pas.common.model.vo.PatentIndexSettingVO;
import cn.cslg.pas.common.model.vo.ProjectImportPatentVO;
import cn.cslg.pas.common.model.vo.PatentBatchIndexVO;
import cn.cslg.pas.mapper.ProjectFieldPatentLinkMapper;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 标引内容关联专利 服务类
 * </p>
 *
 * @author 王岩
 * @since 2022-02-22
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class ProjectFieldPatentLinkService extends ServiceImpl<ProjectFieldPatentLinkMapper, ProjectFieldPatentLink> {

    private final ProjectFieldTextService projectFieldTextService;
    private final ProjectFieldOptionService projectFieldOptionService;
    private final ProjectFieldTreeService projectFieldTreeService;
    private final ProjectFieldService projectFieldService;
    private final LoginUtils loginUtils;

    public List<ProjectFieldPatentLink> getProjectPatentLinkByPatentAndProId(Integer patentId, Integer projectId) {
        LambdaQueryWrapper<ProjectFieldPatentLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProjectFieldPatentLink::getPatentId, patentId);
        queryWrapper.eq(ProjectFieldPatentLink::getProjectId, projectId);
        return this.list(queryWrapper);
    }

    public List<ProjectFieldPatentLink> getProjectPatentLinkByPatentAndProjectIdAndFieldId(Integer patentId, Integer projectId, Integer fieldId) {
        LambdaQueryWrapper<ProjectFieldPatentLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProjectFieldPatentLink::getPatentId, patentId);
        queryWrapper.eq(ProjectFieldPatentLink::getProjectId, projectId);
        queryWrapper.eq(ProjectFieldPatentLink::getFieldId, fieldId);
        return this.list(queryWrapper);
    }

    public ProjectFieldPatentLink getProjectPatentLinkByPatentAndProjectIdAndFieldIdAndOptionId(Integer patentId, Integer projectId, Integer fieldId, Integer optionId) {
        LambdaQueryWrapper<ProjectFieldPatentLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ProjectFieldPatentLink::getPatentId, patentId);
        queryWrapper.eq(ProjectFieldPatentLink::getProjectId, projectId);
        queryWrapper.eq(ProjectFieldPatentLink::getFieldId, fieldId);
        queryWrapper.eq(ProjectFieldPatentLink::getOptionId, optionId);
        return this.getOne(queryWrapper);
    }

    public void updateProjectPatentLink(Integer patentId, Integer type, Integer fieldId, Integer optionId, Integer userId, Integer projectId) {
        ProjectFieldPatentLink projectFieldPatentLink = new ProjectFieldPatentLink();
        projectFieldPatentLink.setType(type);
        projectFieldPatentLink.setPatentId(patentId);
        projectFieldPatentLink.setOptionId(optionId);
        projectFieldPatentLink.setFieldId(fieldId);
        projectFieldPatentLink.setCreateBy(userId);
        projectFieldPatentLink.setProjectId(projectId);
        projectFieldPatentLink.insert();
    }

    public List<ProjectFieldPatentLink> getProjectPatentLinkByPatentIdsAndProjectId(List<Integer> patentIds, Integer projectId) {
        if (patentIds == null || patentIds.size() == 0) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ProjectFieldPatentLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ProjectFieldPatentLink::getPatentId, patentIds);
        queryWrapper.eq(ProjectFieldPatentLink::getProjectId, projectId);
        return this.list(queryWrapper);
    }

    public List<ProjectFieldPatentLink> getProjectPatentLinkByPatentIdsAndFieldId(List<Integer> patentIds, Integer fieldId) {
        if (patentIds == null || patentIds.size() == 0) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<ProjectFieldPatentLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ProjectFieldPatentLink::getPatentId, patentIds);
        queryWrapper.eq(ProjectFieldPatentLink::getFieldId, fieldId);
        return this.list(queryWrapper);
    }

    public void updateProjectFieldPatentLink(ProjectImportPatentVO params, Integer patentId) {
        if (params.getFieldList() != null && params.getFieldList().size() != 0) {
            List<ProjectFieldPatentLink> tempList = this.getProjectPatentLinkByPatentAndProId(patentId, params.getProjectId());
            List<ProjectFieldPatentLink> dataList = new ArrayList<>();
            params.getFieldList().forEach(item -> {
                ProjectFieldPatentLink projectFieldPatentLink = new ProjectFieldPatentLink();
                projectFieldPatentLink.setPatentId(patentId);
                projectFieldPatentLink.setProjectId(params.getProjectId());
                projectFieldPatentLink.setType(item.getType());
                projectFieldPatentLink.setFieldId(item.getFieldId());
                projectFieldPatentLink.setCreateBy(0);
                if (item.getType() == 0 || item.getType() == 1 || item.getType() == 2) {
                    projectFieldPatentLink.setOptionId(projectFieldTextService.add(item.getFieldId(), item.getText()));
                } else {
                    projectFieldPatentLink.setOptionId(item.getOptionId());
                }
                long count = tempList.stream().filter(temp -> temp.getPatentId().equals(patentId) && temp.getFieldId().equals(projectFieldPatentLink.getFieldId()) && temp.getOptionId().equals(projectFieldPatentLink.getOptionId())).count();
                if (count == 0) {
                    dataList.add(projectFieldPatentLink);
                }
            });
            if (dataList.size() != 0) {
                this.saveOrUpdateBatch(dataList);
            }
        }
    }

    public void deleteByFieldId(Integer fieldId) {
        this.remove(Wrappers.<ProjectFieldPatentLink>lambdaQuery().eq(ProjectFieldPatentLink::getFieldId, fieldId));
    }

    public void deleteByOptionId(Integer optionId) {
        this.remove(Wrappers.<ProjectFieldPatentLink>lambdaQuery().eq(ProjectFieldPatentLink::getOptionId, optionId));
    }

    public void deleteByOptionIds(List<Integer> optionIds) {
        if (optionIds != null && optionIds.size() != 0) {
            this.remove(Wrappers.<ProjectFieldPatentLink>lambdaQuery().in(ProjectFieldPatentLink::getOptionId, optionIds));
        }
    }

    public void deleteByPatentIdAndProjectIdAndFieldId(Integer patentId, Integer projectId, Integer fieldId) {
        this.remove(Wrappers.<ProjectFieldPatentLink>lambdaQuery().eq(ProjectFieldPatentLink::getFieldId, fieldId).eq(ProjectFieldPatentLink::getProjectId, projectId).eq(ProjectFieldPatentLink::getPatentId, patentId));
    }

    public void deleteByPatentIdsAndProjectIdAndFieldId(List<Integer> patentIds, Integer projectId, Integer fieldId) {
        LambdaQueryWrapper<ProjectFieldPatentLink> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(ProjectFieldPatentLink::getPatentId, patentIds);
        queryWrapper.eq(ProjectFieldPatentLink::getProjectId, projectId);
        queryWrapper.eq(ProjectFieldPatentLink::getFieldId, fieldId);
        this.remove(queryWrapper);
    }

    @Transactional
    public void patentBatchIndex(PatentBatchIndexVO params) {
        List<ProjectFieldPatentLink> tempList;
        List<ProjectField> fieldList = params.getFieldList().stream().filter(ProjectField::getEnabled).collect(Collectors.toList());
        List<ProjectFieldPatentLink> projectFieldPatentLinkList = new ArrayList<>();
        for (ProjectField field : fieldList) {
            switch (field.getType()) {
                case 0:
                case 1:
                case 2:
                    this.deleteByPatentIdsAndProjectIdAndFieldId(params.getPatentIds(), params.getProjectId(), field.getId());
                    tempList = this.getProjectPatentLinkByPatentIdsAndProjectId(params.getPatentIds(), params.getProjectId());
                    tempList = tempList.stream().filter(item -> fieldList.stream().map(ProjectField::getId).collect(Collectors.toList()).contains(item.getFieldId())).collect(Collectors.toList());
                    ProjectFieldText projectFieldText = projectFieldTextService.getProjectFieldTextByNameAndFieldId(field.getText(), field.getId());
                    if (projectFieldText == null) {
                        projectFieldText = new ProjectFieldText();
                        projectFieldText.setText(field.getText());
                        projectFieldText.setFieldId(field.getId());
                        projectFieldText.insert();
                    }
                    projectFieldPatentLinkList.addAll(this.setPatentBatchIndexDataList(tempList, params.getPatentIds(), field, projectFieldText.getId(), params.getProjectId()));
                    break;
                case 3:
                case 4:
                    this.deleteByPatentIdsAndProjectIdAndFieldId(params.getPatentIds(), params.getProjectId(), field.getId());
                case 5:
                case 6:
                    tempList = this.getProjectPatentLinkByPatentIdsAndProjectId(params.getPatentIds(), params.getProjectId());
                    tempList = tempList.stream().filter(item -> fieldList.stream().map(ProjectField::getId).collect(Collectors.toList()).contains(item.getFieldId())).collect(Collectors.toList());
                    for (Integer optionId : field.getSelected()) {
                        projectFieldPatentLinkList.addAll(this.setPatentBatchIndexDataList(tempList, params.getPatentIds(), field, optionId, params.getProjectId()));
                    }
                    break;
            }
        }
        if (projectFieldPatentLinkList.size() != 0) {
            this.saveOrUpdateBatch(projectFieldPatentLinkList);
        }
    }

    private List<ProjectFieldPatentLink> setPatentBatchIndexDataList(List<ProjectFieldPatentLink> tempList, List<Integer> patentIds, ProjectField field, Integer optionId, Integer projectId) {
        List<ProjectFieldPatentLink> dataList = new ArrayList<>();
        for (Integer patentId : patentIds) {
            ProjectFieldPatentLink temp = tempList.stream().filter(item -> item.getFieldId().equals(field.getId()) && item.getOptionId().equals(optionId) && item.getPatentId().equals(patentId)).findFirst().orElse(null);
            if (temp == null) {
                ProjectFieldPatentLink projectFieldPatentLink = new ProjectFieldPatentLink();
                projectFieldPatentLink.setFieldId(field.getId());
                projectFieldPatentLink.setProjectId(projectId);
                projectFieldPatentLink.setType(field.getType());
                projectFieldPatentLink.setCreateBy(loginUtils.getId());
                projectFieldPatentLink.setOptionId(optionId);
                projectFieldPatentLink.setPatentId(patentId);
                dataList.add(projectFieldPatentLink);
            }
        }
        return dataList;
    }

    public List<CustomFieldLabelDTO> getPatentIndexSetting2(Integer patentId, Integer projectId) {
        List<CustomFieldLabelDTO> dataList = new ArrayList<>();
        List<ProjectField> projectFieldList = projectFieldService.getProjectFieldByProjectId(projectId);
        for (ProjectField projectField : projectFieldList) {
            PatentIndexSettingVO params = new PatentIndexSettingVO();
            CustomFieldLabelDTO data = new CustomFieldLabelDTO();
            params.setId(patentId);
            params.setType(projectField.getType());
            params.setFieldId(projectField.getId());
            params.setProjectId(projectId);
            data.setName(projectField.getName());
            data.setId(projectField.getId());
            data.setType(projectField.getType());
            data.setSelected(this.getPatentIndexSetting(params));
            dataList.add(data);
        }
        return dataList;
    }

    public List<LabelDTO> getPatentIndexSetting(PatentIndexSettingVO params) {
        List<ProjectFieldPatentLink> projectFieldPatentLinkList = this.getProjectPatentLinkByPatentAndProjectIdAndFieldId(params.getId(), params.getProjectId(), params.getFieldId());
        List<Integer> optionIds = projectFieldPatentLinkList.stream().map(ProjectFieldPatentLink::getOptionId).collect(Collectors.toList());
        List<LabelDTO> mapList = new ArrayList<>();
        switch (params.getType()) {
            case 0:
            case 1:
            case 2:
                List<ProjectFieldText> projectFieldTextList = projectFieldTextService.getProjectFieldTextByIds(optionIds);
                for (ProjectFieldText projectFieldText : projectFieldTextList) {
                    LabelDTO map = new LabelDTO();
                    map.setValue(projectFieldText.getId());
                    map.setLabel(projectFieldText.getText());
                    mapList.add(map);
                }
                break;
            case 3:
            case 4:
            case 5:
                List<ProjectFieldOption> projectFieldOptionList = projectFieldOptionService.getFieldOptionListByIds(optionIds);
                for (ProjectFieldOption projectFieldOption : projectFieldOptionList) {
                    LabelDTO map = new LabelDTO();
                    map.setValue(projectFieldOption.getId());
                    map.setLabel(projectFieldOption.getName());
                    mapList.add(map);
                }
                break;
            case 6:
                List<ProjectFieldTree> projectFieldTreeList = projectFieldTreeService.getProjectFieldTreeOptionByIds(optionIds);
                for (ProjectFieldTree projectFieldTree : projectFieldTreeList) {
                    LabelDTO map = new LabelDTO();
                    map.setValue(projectFieldTree.getId());
                    map.setLabel(projectFieldTree.getName());
                    mapList.add(map);
                }
                break;
        }
        return mapList;
    }

    @Transactional
    public void updatePatentIndexSetting(PatentIndexSettingVO params) {
        this.deleteByPatentIdAndProjectIdAndFieldId(params.getId(), params.getProjectId(), params.getFieldId());
        List<Integer> optionIds = params.getSelected().stream().map(LabelDTO::getValue).distinct().collect(Collectors.toList());
        List<String> texts = params.getSelected().stream().map(LabelDTO::getLabel).distinct().collect(Collectors.toList());
        List<ProjectFieldPatentLink> projectFieldPatentLinkList = new ArrayList<>();
        switch (params.getType()) {
            case 0:
            case 1:
            case 2:
                List<ProjectFieldText> tempList = projectFieldTextService.getProjectFieldTextByFieldId(params.getFieldId());
                for (String text : texts) {
                    if (StringUtils.isEmpty(text)) {
                        continue;
                    }
                    ProjectFieldText projectFieldText = tempList.stream().filter(item -> item.getText().equals(text)).findFirst().orElse(null);
                    if (projectFieldText == null) {
                        projectFieldText = new ProjectFieldText();
                        projectFieldText.setFieldId(params.getFieldId());
                        projectFieldText.setText(text);
                        projectFieldText.insert();
                    }
                    ProjectFieldPatentLink projectFieldPatentLink = new ProjectFieldPatentLink();
                    projectFieldPatentLink.setProjectId(params.getProjectId());
                    projectFieldPatentLink.setPatentId(params.getId());
                    projectFieldPatentLink.setType(params.getType());
                    projectFieldPatentLink.setFieldId(params.getFieldId());
                    projectFieldPatentLink.setCreateBy(loginUtils.getId());
                    projectFieldPatentLink.setOptionId(projectFieldText.getId());
                    projectFieldPatentLinkList.add(projectFieldPatentLink);
                }
                break;
            case 3:
            case 4:
            case 5:
            case 6:
                for (Integer optionId : optionIds) {
                    ProjectFieldPatentLink projectFieldPatentLink = new ProjectFieldPatentLink();
                    projectFieldPatentLink.setProjectId(params.getProjectId());
                    projectFieldPatentLink.setPatentId(params.getId());
                    projectFieldPatentLink.setType(params.getType());
                    projectFieldPatentLink.setFieldId(params.getFieldId());
                    projectFieldPatentLink.setCreateBy(loginUtils.getId());
                    projectFieldPatentLink.setOptionId(optionId);
                    projectFieldPatentLinkList.add(projectFieldPatentLink);
                }
                break;
        }
        if (projectFieldPatentLinkList.size() != 0) {
            this.saveOrUpdateBatch(projectFieldPatentLinkList);
        }
    }

    public void importProjectFieldPatentLink(List<Patent> importPatentList, List<Patent> localPatentList, List<ProjectFieldPatentLink> importProjectPatentLinkList, Integer projectId, Integer userId, Integer importProjectFieldId, Integer importProjectFieldOptionId, Integer localProjectFieldId, Integer localProjectFieldOptionId) {
        List<ProjectFieldPatentLink> importProjectFieldPatentLinkList = importProjectPatentLinkList.stream().filter(item -> item.getFieldId().equals(importProjectFieldId) && item.getOptionId().equals(importProjectFieldOptionId)).collect(Collectors.toList());
        for (ProjectFieldPatentLink projectFieldPatentLink : importProjectFieldPatentLinkList) {
            Patent importPatent = importPatentList.stream().filter(item -> item.getId().equals(projectFieldPatentLink.getPatentId())).findFirst().orElse(new Patent());
            Patent localPatent = localPatentList.stream().filter(item -> item.getPatentNo().equals(importPatent.getPatentNo())).findFirst().orElse(null);
            if (localPatent == null) {
                continue;
            }
            projectFieldPatentLink.setId(null);
            projectFieldPatentLink.setCreateBy(userId);
            projectFieldPatentLink.setProjectId(projectId);
            projectFieldPatentLink.setPatentId(localPatent.getId());
            projectFieldPatentLink.setFieldId(localProjectFieldId);
            projectFieldPatentLink.setOptionId(localProjectFieldOptionId);
        }
        this.saveOrUpdateBatch(importProjectFieldPatentLinkList);
    }
}
