package com.diagbot.facade;

import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.diagbot.client.UserServiceClient;
import com.diagbot.dto.GetRetrievalsByTagDTO;
import com.diagbot.dto.RespDTO;
import com.diagbot.dto.RetrievalExcelImDTO;
import com.diagbot.dto.RetrievalListDTO;
import com.diagbot.entity.QuestionInfo;
import com.diagbot.entity.Retrieval;
import com.diagbot.entity.RetrievalMapping;
import com.diagbot.enums.IsDeleteEnum;
import com.diagbot.exception.CommonErrorCode;
import com.diagbot.exception.CommonException;
import com.diagbot.service.RetrievalMappingService;
import com.diagbot.service.RetrievalService;
import com.diagbot.service.impl.RetrievalServiceImpl;
import com.diagbot.util.DateUtil;
import com.diagbot.util.ListUtil;
import com.diagbot.util.StringUtil;
import com.diagbot.util.UserUtils;
import com.diagbot.vo.AddTagRetrievalDetailVO;
import com.diagbot.vo.AddTagRetrievalVO;
import com.diagbot.vo.DelRetrievalsByQuesIdVO;
import com.diagbot.vo.GetRetrievalsByTagVO;
import com.diagbot.vo.RetrievalListVO;

/**
 * @author rgb
 * @Description
 * @time 2018年12月5日下午4:53:59
 */
@Component
public class RetrievalFacade extends RetrievalServiceImpl {

    @Autowired
    private RetrievalMappingFacade retrievalMappingFacade;
    @Autowired
    private QuestionFacade questionFacade;
    @Autowired
    private UserServiceClient userServiceClient;
    @Autowired
    @Qualifier("retrievalServiceImpl")
    private RetrievalService retrievalService;
    @Autowired
    @Qualifier("retrievalMappingServiceImpl")
    private RetrievalMappingService retrievalMappingService;
    

    /**
     * 根据标签获取同义词
     *
     * @param getRetrievalsByTagVO
     * @return
     */
    public Map<Integer, List<GetRetrievalsByTagDTO>> getRetrievalsByTag(GetRetrievalsByTagVO getRetrievalsByTagVO) {
        List<GetRetrievalsByTagDTO> retList = baseMapper.getRetrievalsByTag(getRetrievalsByTagVO);
        if (ListUtil.isEmpty(retList)) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS);
        }
        
        Map<Integer, List<GetRetrievalsByTagDTO>> retMap = retList.stream().collect(Collectors.groupingBy(GetRetrievalsByTagDTO::getRetrievalType));
        
        return retMap;
    }

    /**
     * 根据映射关系删除标签的同义词
     *
     * @param delRetrievalsByQuesIdVO
     * @return
     */
    public Boolean delRetrievalsByQuesId(DelRetrievalsByQuesIdVO delRetrievalsByQuesIdVO) {
        QueryWrapper<RetrievalMapping> mappingQe = new QueryWrapper<>();
        mappingQe.eq("question_id", delRetrievalsByQuesIdVO.getQuestionId());
        if (retrievalMappingFacade.count(mappingQe) == 0) {
            throw new CommonException(CommonErrorCode.NOT_EXISTS);
        }
        String userId = UserUtils.getCurrentPrincipleID();
        RetrievalMapping retrievalMapping = new RetrievalMapping();
        retrievalMapping.setGmtModified(DateUtil.now());
        retrievalMapping.setModifier(userId);
        retrievalMapping.setIsDeleted(IsDeleteEnum.Y.getKey());

        retrievalMappingFacade.update(retrievalMapping, mappingQe);
        return true;
    }

    /**
     * 添加或者编辑标签同义词
     *
     * @param addTagRetrievalVO
     * @return
     */
    public Boolean addTagRetrieval(AddTagRetrievalVO addTagRetrievalVO) {
        if (addTagRetrievalVO.getItemList().stream().distinct().count() != addTagRetrievalVO.getItemList().size()) {
            throw new CommonException(CommonErrorCode.RPC_ERROR,
                    "同义词中存在重复数据("+addTagRetrievalVO.getQuestionName()+")！");
        }
        
        long typeOneCou = addTagRetrievalVO.getItemList().stream().filter(i->i.getRetrievalType()==1).count();
        if(typeOneCou==0){
        	throw new CommonException(CommonErrorCode.RPC_ERROR,
                    "本体必须传("+addTagRetrievalVO.getQuestionName()+")！");
        }
        if(typeOneCou>1){
        	throw new CommonException(CommonErrorCode.RPC_ERROR,
                    "本体只能有一个("+addTagRetrievalVO.getQuestionName()+")！");
        }

        Date now = DateUtil.now();
        String userId = UserUtils.getCurrentPrincipleID();

        Map<String, AddTagRetrievalDetailVO> detailMap = addTagRetrievalVO.getItemList().stream().collect(Collectors.toMap(AddTagRetrievalDetailVO::getRetrievalName, i -> i));
        List<String> retrievalNames = addTagRetrievalVO.getItemList().stream().map(i -> i.getRetrievalName()).collect(Collectors.toList());

        QueryWrapper<Retrieval> retrievalQe = new QueryWrapper<Retrieval>();
        retrievalQe.in("name", retrievalNames);
        retrievalQe.eq("is_deleted", IsDeleteEnum.N.getKey());
        Map<String, Retrieval> retrievalMap = this.list(retrievalQe).stream().collect(Collectors.toMap(Retrieval::getName, i -> i));

        List<Retrieval> saveOrUpdateRetrievals = new ArrayList<>();
        List<Retrieval> retrievals = new ArrayList<>();
        addTagRetrievalVO.getItemList().forEach(i -> {
            Retrieval retrieval = retrievalMap.get(i.getRetrievalName());
            if (retrieval == null) {
                retrieval = new Retrieval();
                retrieval.setName(i.getRetrievalName());
                retrieval.setSpell(i.getRetrievalSpell());
                retrieval.setCreator(userId);
                retrieval.setGmtCreate(now);
                retrieval.setModifier(userId);
                retrieval.setGmtModified(now);
                saveOrUpdateRetrievals.add(retrieval);
            } else if (!retrieval.getSpell().equals(i.getRetrievalSpell())) {
                retrieval.setSpell(i.getRetrievalSpell());
                retrieval.setModifier(userId);
                retrieval.setGmtModified(now);
                saveOrUpdateRetrievals.add(retrieval);
            } else {
                retrievals.add(retrieval);
            }
        });
        if(saveOrUpdateRetrievals.size()>0){
        	retrievalService.saveOrUpdateBatch(saveOrUpdateRetrievals);
        }
        retrievals.addAll(saveOrUpdateRetrievals);
        List<Long> retrievalIds = retrievals.stream().map(i -> i.getId()).collect(Collectors.toList());

        QueryWrapper<RetrievalMapping> retrievalMappingQe = new QueryWrapper<RetrievalMapping>();
        retrievalMappingQe.eq("question_id", addTagRetrievalVO.getQuestionId());
        List<RetrievalMapping> retrievalMappings = retrievalMappingFacade.list(retrievalMappingQe);
        Map<Long, RetrievalMapping> retrievalMappingMap = retrievalMappings.stream().collect(Collectors.toMap(RetrievalMapping::getRetrievalId, i -> i));

        List<RetrievalMapping> addOrUpdateRetrievalMappings = new ArrayList<>();
        retrievalMappings.stream().filter(i ->i.getIsDeleted().equals(IsDeleteEnum.N.getKey())&&!retrievalIds.contains(i.getRetrievalId())).forEach(i -> {
            i.setIsDeleted(IsDeleteEnum.Y.getKey());
            i.setGmtModified(now);
            i.setModifier(userId);
            addOrUpdateRetrievalMappings.add(i);
        });

        retrievals.forEach(i -> {
            RetrievalMapping retrievalMapping = retrievalMappingMap.get(i.getId());
            AddTagRetrievalDetailVO detail = detailMap.get(i.getName());
            if (retrievalMapping == null) {
                retrievalMapping = new RetrievalMapping();
                retrievalMapping.setQuestionId(addTagRetrievalVO.getQuestionId());
                retrievalMapping.setRetrievalId(i.getId());
                retrievalMapping.setGmtCreate(now);
                retrievalMapping.setGmtModified(now);
                retrievalMapping.setCreator(userId);
                retrievalMapping.setModifier(userId);
                retrievalMapping.setShowType(detail.getRetrievalType());
                addOrUpdateRetrievalMappings.add(retrievalMapping);
            } else {
                if (detail.getRetrievalType() != retrievalMapping.getShowType()
                        || retrievalMapping.getIsDeleted().equals(IsDeleteEnum.Y.getKey())) {
                    retrievalMapping.setShowType(detailMap.get(i.getName()).getRetrievalType());
                    retrievalMapping.setGmtModified(now);
                    retrievalMapping.setModifier(userId);
                    retrievalMapping.setIsDeleted(IsDeleteEnum.N.getKey());
                    addOrUpdateRetrievalMappings.add(retrievalMapping);
                }
            }
        });

        if(ListUtil.isNotEmpty(addOrUpdateRetrievalMappings)){
        	retrievalMappingService.saveOrUpdateBatch(addOrUpdateRetrievalMappings);
        }
        return true;
    }
    
    /**
     * 获取标签同义词列表
     *
     * @param retrievalListVO
     * @return
     */
    public IPage<RetrievalListDTO> retrievalList(RetrievalListVO retrievalListVO) {
        IPage<RetrievalListDTO> ipage = this.getRetrievalList(retrievalListVO);

        List<RetrievalListDTO> retrievalListDTOList = ipage.getRecords();
        if (ListUtil.isEmpty(retrievalListDTOList)) {
            return ipage;
        }

        List<Long> questionIds = retrievalListDTOList.stream().map(i -> i.getQuestionId()).collect(Collectors.toList());

        QueryWrapper<RetrievalMapping> retrievalMappingQe = new QueryWrapper<RetrievalMapping>();
        retrievalMappingQe.in("question_id", questionIds);
        List<RetrievalMapping> retrievalMappings = retrievalMappingFacade.list(retrievalMappingQe);
        Map<Long, List<RetrievalMapping>> retrievalMappingListMap = retrievalMappings.stream().collect(Collectors.groupingBy(RetrievalMapping::getQuestionId));

        List<Long> retrievalIds = retrievalMappings.stream().map(i -> i.getRetrievalId()).distinct().collect(Collectors.toList());
        Map<Long, Retrieval> retrievalMap = this.listByIds(retrievalIds).stream().filter(i -> i.getIsDeleted().equals("N")).collect(Collectors.toMap(Retrieval::getId, i -> i));

        retrievalListDTOList.forEach(retrievalListDTO -> {
            List<RetrievalMapping> retrievalMappingList = retrievalMappingListMap.get(retrievalListDTO.getQuestionId());
            retrievalMappingList = retrievalMappingList.stream().filter(i -> retrievalMap.get(i.getRetrievalId())!=null).sorted((t1, t2) -> t2.getGmtModified().compareTo(t1.getGmtModified())).collect(Collectors.toList());
            retrievalListDTO.setOperatorName(retrievalMappingList.get(0).getModifier());
            retrievalListDTO.setRetrievalSelfName(retrievalMappingList.stream().filter(i -> i.getShowType() == 1 && i.getIsDeleted().equals("N")).map(i -> retrievalMap.get(i.getRetrievalId()).getName()).collect(Collectors.joining("、")));
            retrievalListDTO.setRetrievalNames(retrievalMappingList.stream().filter(i -> i.getShowType() == 2 && i.getIsDeleted().equals("N")).map(i -> retrievalMap.get(i.getRetrievalId()).getName()).collect(Collectors.joining("、")));
            retrievalListDTO.setRetrievalSonNames(retrievalMappingList.stream().filter(i -> i.getShowType() == 3 && i.getIsDeleted().equals("N")).map(i -> retrievalMap.get(i.getRetrievalId()).getName()).collect(Collectors.joining("、")));
        });

        List<String> ids = retrievalListDTOList.stream().map(i -> i.getOperatorName()).collect(Collectors.toList());
        RespDTO<Map<String, String>> respDTO = userServiceClient.getUserInfoByIds(ids);
        if (respDTO == null || !CommonErrorCode.OK.getCode().equals(respDTO.code)) {
            throw new CommonException(CommonErrorCode.RPC_ERROR,
                    "获取用户信息失败");
        }

        retrievalListDTOList.forEach(i -> i.setOperatorName(respDTO.data.get(i.getOperatorName())));
        ipage.setRecords(retrievalListDTOList);
        return ipage;
    }

    /**
     * 同义词excel文件导入
     *
     * @param file
     * @return
     */
    public RetrievalExcelImDTO retrievalExcelIm(MultipartFile file) {
        List<AddTagRetrievalVO> addTagRetrievalVOList = new ArrayList<>();
        StringBuffer sbf = new StringBuffer();
        InputStream inputStream = null;
        Workbook wb = null;
        try {
            if (!file.isEmpty()) {
                inputStream = file.getInputStream();
                if (inputStream.available() > 512000) {
                    sbf.append("文件最大支持500KB！").append("<br/>");
                } else {
                    String fileName = file.getOriginalFilename();
                    if (fileName.lastIndexOf(".") != -1) {
                        String type = fileName.substring(fileName.lastIndexOf("."));
                        if (type.equals(".xls")) {
                            wb = new HSSFWorkbook(inputStream);
                        } else if (type.equals(".xlsx")) {
                            wb = new XSSFWorkbook(inputStream);
                        }
                        if (wb != null) {
                            List<AddTagRetrievalDetailVO> detailList = new ArrayList<>();
                            Sheet sheet = wb.getSheetAt(0);
                            int count = 0;
                            String questionName, retrievalName, retrievalSpell, retrievalType;
                            for (Row row : sheet) {
                                count++;
                                if (count == 1 || row == null) {
                                    continue;
                                }
                                questionName = getValue(row.getCell(0)).trim().replace(" ", "");
                                retrievalName = getValue(row.getCell(1)).trim().replace(" ", "");
                                retrievalSpell = getValue(row.getCell(2)).trim().replace(" ", "");
                                retrievalType = getValue(row.getCell(3)).trim().replace(" ", "");
                                if (StringUtil.isEmpty(questionName) || StringUtil.isEmpty(retrievalName)
                                        || StringUtil.isEmpty(retrievalSpell) || StringUtil.isEmpty(retrievalType)) {
                                    sbf.append("第" + count + "行数据不完整！").append("<br/>");
                                    continue;
                                }

                                AddTagRetrievalDetailVO addTagRetrievalDetailVO = new AddTagRetrievalDetailVO();
                                addTagRetrievalDetailVO.setQuestionName(questionName);
                                addTagRetrievalDetailVO.setRetrievalName(retrievalName);
                                addTagRetrievalDetailVO.setRetrievalSpell(retrievalSpell);
                                addTagRetrievalDetailVO.setRetrievalType(Integer.parseInt(retrievalType));
                                detailList.add(addTagRetrievalDetailVO);
                            }

                            if (detailList.size() > 0) {
                                List<String> questionNames = detailList.stream().map(i -> i.getQuestionName()).distinct().collect(Collectors.toList());
                                QueryWrapper<QuestionInfo> questionInfoQe = new QueryWrapper<>();
                                questionInfoQe.in("tag_name", questionNames);
                                List<QuestionInfo> questionInfos = questionFacade.list(questionInfoQe);
                                if (questionInfos.size() > 0) {
                                    Map<String, Long> questionIdMap = questionInfos.stream().collect(Collectors.toMap(QuestionInfo::getTagName, i -> i.getId()));
                                    detailList.forEach(i -> {
                                        i.setQuestionId(questionIdMap.get(i.getQuestionName()));
                                    });
                                    Map<Long, List<AddTagRetrievalDetailVO>> detailMap = detailList.stream().collect(Collectors.groupingBy(AddTagRetrievalDetailVO::getQuestionId));
                                    for (Long key : detailMap.keySet()) {
                                        AddTagRetrievalVO addTagRetrievalVO = new AddTagRetrievalVO();
                                        addTagRetrievalVO.setQuestionId(key);
                                        addTagRetrievalVO.setItemList(detailMap.get(key));
                                        addTagRetrievalVOList.add(addTagRetrievalVO);
                                    }
                                }
                            }
                        } else {
                            sbf.append("非excel文件无法解析！").append("<br/>");
                        }
                    } else {
                        sbf.append("未知文件无法解析！").append("<br/>");
                    }
                }
            } else {
                sbf.append("无文件上传！").append("<br/>");
            }
        } catch (Exception e) {
            sbf.append("解析失败！").append("<br/>");
        } finally {
            try {
                if (wb != null) {
                    wb.close();
                }
                if (inputStream != null) {
                    inputStream.close();
                }
            } catch (Exception e) {
            }
        }
        
        if(sbf.length()>0){
        	throw new CommonException(CommonErrorCode.RPC_ERROR,sbf.toString());
        }

        addTagRetrievalVOList.forEach(i -> {
            addTagRetrieval(i);
        });

        RetrievalExcelImDTO retrievalExcelImDTO = new RetrievalExcelImDTO();
        return retrievalExcelImDTO;
    }

    @SuppressWarnings("deprecation")
    private String getValue(Cell cell) {
        try {
            Object obj = null;
            switch (cell.getCellTypeEnum()) {
                case BOOLEAN:
                    obj = cell.getBooleanCellValue();
                    break;
                case ERROR:
                    obj = cell.getErrorCellValue();
                    break;
                case NUMERIC:
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        Date date = cell.getDateCellValue();
                        obj = DateFormatUtils.format(date, "yyyy-MM-dd");
                    } else {
                        obj = cell.getNumericCellValue();
                        DecimalFormat df = new DecimalFormat("0");
                        obj = df.format(obj);
                    }

                    // obj = cell.getNumericCellValue();
                    break;
                case STRING:
                    obj = cell.getStringCellValue();
                    break;
                default:
                    break;
            }
            return obj.toString();
        } catch (Exception e) {
            return "";
        }
    }

}
