/*
 * Author: wangjian
 * 生成ServiceImpl
 */
package com.tofly.dispatch.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.common.oauth.exception.ToflyDeniedException;
import com.tofly.dispatch.common.FlowConstant;
import com.tofly.dispatch.dto.BatchDispatchInfoDto;
import com.tofly.dispatch.dto.DispatchInfoDto;
import com.tofly.dispatch.dto.LoadDispatchInfoDto;
import com.tofly.dispatch.dto.UpdateDispatchInfoDto;
import com.tofly.dispatch.em.Constant;
import com.tofly.dispatch.em.ExcelExportFileTypeEnum;
import com.tofly.dispatch.entity.Dispatch;
import com.tofly.dispatch.entity.DispatchInfo;
import com.tofly.dispatch.mapper.DispatchInfoMapper;
import com.tofly.dispatch.service.DispatchInfoService;
import com.tofly.dispatch.service.DispatchService;
import com.tofly.dispatch.strategy.ExcelStrategyContext;
import com.tofly.dispatch.util.ExcelUtil;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 供水调度详情（水压）
 *
 * @author xqf
 * @date Mon Mar 14 00:00:00 CST 2022
 */
@Service("dispatchInfoService")
public class DispatchInfoServiceImpl extends ServiceImpl<DispatchInfoMapper, DispatchInfo> implements DispatchInfoService {

    @Autowired
    private DispatchService dispatchService;

    @Autowired
    private ExcelStrategyContext excelStrategyContext;

    /**
     * 批量保存调度数据
     * @param dtos 调度数据集合
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object saveDispatchInfo(BatchDispatchInfoDto dtos) {
        String str = isDispatch(dtos.getDispatchId());
        if(StringUtils.isNotEmpty(str)){
            return str;
        }
        List<DispatchInfo> infos = new ArrayList<>();
        str = getDispatchData(dtos.getDispatchId(),dtos.getDtos(), infos);
        if(StringUtils.isNotEmpty(str)){
            return str;
        }
        this.remove(new QueryWrapper<DispatchInfo>().lambda().eq(DispatchInfo::getDispatchId,dtos.getDispatchId()));
        for (DispatchInfo info:infos) {
            this.save(info);
        }
        return true;
    }

    /**
     * 封装调度方案数据
     * @param id 调度方案id
     * @param dtos 设备数据集合
     * @param infos 处理后设备数据集合
     * @return
     */
    private String getDispatchData(Long id,List<DispatchInfoDto> dtos, List<DispatchInfo> infos) {
        List<String> names = new ArrayList<>();
        for (DispatchInfoDto dto: dtos) {
            DispatchInfo info = new DispatchInfo();
            BeanUtils.copyProperties(dto,info);
            if(StringUtils.isEmpty(info.getSiteName())){
                return FlowConstant.NAME_ISNULL;
            }
            if(names.contains(info.getSiteName())){
                return FlowConstant.NAME_EXISTS;
            }
            info.setDispatchId(id);
            info.setIsValid(FlowConstant.SHORT_ONE);
            info.setIsDel(FlowConstant.SHORT_ZERO);
            infos.add(info);
        }
        return null;
    }

    /**
     * 判断调度方案是否存在是否合适
     * @param id 调度方案id
     * @return
     */
    private String isDispatch(Long id){
        Dispatch dispatch =dispatchService.getById(id);
        if(dispatch==null){
            return FlowConstant.DATA_NOTHINGNESS;
        }
        int count = dispatchService.upDispatchCount(id,dispatch.getDispatchType());
        if((FlowConstant.SHORT_TWO==dispatch.getDispatchType()&&count!=2)
                ||(FlowConstant.SHORT_TWO!=dispatch.getDispatchType()&&count!=1)){
            return FlowConstant.DISPATCH_ERROR;
        }
        return null;
    }

    /**
     * 文件上传保存调度方案数据
     * @param id 调度方案id
     * @param fileList 调度设备文件
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object saveDispatchInfo(Long id, MultipartFile fileList) {
        if(fileList==null||fileList.isEmpty()){
            return FlowConstant.FILE_ISNULL;
        }
        String str = isDispatch(id);
        if(StringUtils.isNotEmpty(str)){
            return str;
        }
        List<DispatchInfoDto> dtos = null;
        try {
            dtos = getExeData(fileList,"");
        }catch (Exception e){
            return FlowConstant.FILE_ERROR;
        }
        if(CollUtil.isEmpty(dtos)){
            return FlowConstant.DATA_NOTHINGNESS;
        }
        List<DispatchInfo> infos = new ArrayList<>();
        str = getDispatchData(id,dtos, infos);
        if(StringUtils.isNotEmpty(str)){
            return str;
        }
        this.remove(new QueryWrapper<DispatchInfo>().lambda().eq(DispatchInfo::getDispatchId,id));
        for (DispatchInfo info:infos) {
            this.save(info);
        }

        return true;
    }

    /**
     * 修改调度方案站点信息
     * @param dto 信息数据
     * @return
     */
    @Override
    public Object updateDispatchInfoDto(UpdateDispatchInfoDto dto) {
        DispatchInfo dispatchInfo = this.getById(dto.getId());
        if(dispatchInfo == null){
            return FlowConstant.DATA_NOTHINGNESS;
        }
        if(StringUtils.isNotEmpty(dto.getSiteName())) {
            int count = this.count(new QueryWrapper<DispatchInfo>().lambda()
                    .eq(DispatchInfo::getSiteName,dto.getSiteName())
                    .ne(DispatchInfo::getId, dto.getId())
                    .eq(DispatchInfo::getDispatchId,dispatchInfo.getDispatchId())
                    .eq(DispatchInfo::getIsDel, FlowConstant.SHORT_ZERO));
            if(count>0) {
                return FlowConstant.NAME_EXISTS;
            }
        }
        DispatchInfo info = new DispatchInfo();
        BeanUtils.copyProperties(dto,info);
        return this.updateById(info);
    }

    @Override
    @SneakyThrows
    public Object exportOrPageDispatchInfo(HttpServletResponse response, Page page, LoadDispatchInfoDto vo) {
        LambdaQueryWrapper qw = new QueryWrapper<DispatchInfo>().lambda()
                .eq(vo.getId()!=null,DispatchInfo::getId,vo.getId())
                .eq(vo.getDispatchId()!=null,DispatchInfo::getDispatchId,vo.getDispatchId())
                .like(StringUtils.isNotEmpty(vo.getSiteName()),DispatchInfo::getSiteName,vo.getSiteName())
                .eq(DispatchInfo::getIsDel,FlowConstant.SHORT_ZERO)
                .orderByAsc(DispatchInfo::getId);
        if(vo.getIsExport()!=null&&vo.getIsExport()){
            List<DispatchInfo> infos = this.list(qw);

            // 根据templateServiceType,templateFlag获取对应模板数据
            ExcelExportFileTypeEnum excelExportFileTypeEnum = ExcelExportFileTypeEnum.getExcelExportFileTypeEnum("exportService", "1");
            if (null == excelExportFileTypeEnum) {
                throw new ToflyDeniedException("导出失败");
            }
            //将查询的结果转json字符串的格式，因为导出的时候只能传一个字符串
            String resultListToString = JSONArray.toJSONStringWithDateFormat(infos, "yyyy-MM-dd HH:mm:ss");
            // 从模型类型枚举根据templateServiceType获取策略对应模板数据
            List<Map<String, Object>> dataList = excelStrategyContext.getExportData("exportService", "1", resultListToString);
            ExcelUtil.export(dataList.get(0), excelExportFileTypeEnum, Constant.FILE_PATH_TEST_EXPORT_EXCEL, response);
            return true;
        }else {
            Page<DispatchInfo> pg = this.page(page, qw);
            return pg;
        }
    }

    /**
     * 文件转换为对象数据
     * @param fileList 上传的文件
     * @param sheetName sheet名称
     * @return List<DispatchInfoDto>
     * @throws Exception
     */
    private List<DispatchInfoDto> getExeData(MultipartFile fileList, String sheetName) throws Exception {
        InputStream inputStream = fileList.getInputStream();
        com.tofly.common.core.util.io.ExcelUtil opsExcel = new com.tofly.common.core.util.io.ExcelUtil(DispatchInfoDto.class);
        List<DispatchInfoDto> ips = opsExcel.importExcel(sheetName, inputStream);
        return ips;
    }

}
