package com.tuoheng.admin.service.airData.query;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.tuoheng.admin.constant.SystemConstant;
import com.tuoheng.admin.entity.domain.AirData;
import com.tuoheng.admin.entity.domain.AirDataExport;
import com.tuoheng.admin.entity.domain.Inspection;
import com.tuoheng.admin.entity.domain.User;
import com.tuoheng.admin.entity.vo.airData.AirDataExcelVo;
import com.tuoheng.admin.enums.AirDataEnum;
import com.tuoheng.admin.enums.MarkEnum;
import com.tuoheng.admin.mapper.AirDataExportMapper;
import com.tuoheng.admin.mapper.AirDataMapper;
import com.tuoheng.admin.mapper.InspectionMapper;
import com.tuoheng.admin.utils.AliyunOSSUtil;
import com.tuoheng.admin.utils.CurrentUserUtil;
import com.tuoheng.common.core.config.UploadFileConfig;
import com.tuoheng.common.core.enums.ServiceExceptionEnum;
import com.tuoheng.common.core.exception.ServiceException;
import com.tuoheng.common.core.utils.DateUtils;
import com.tuoheng.common.core.utils.FileUtils;
import com.tuoheng.common.core.utils.JsonResult;
import com.tuoheng.common.core.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author ChengWang
 * @Date 2023/5/24
 */
@Service
@Slf4j
public class QueryAirDataListService {

    @Autowired
    private AirDataMapper airDataMapper;

    @Autowired
    private InspectionMapper inspectionMapper;

    @Autowired
    private AirDataExportMapper airDataExportMapper;

    @Autowired
    private AliyunOSSUtil aliyunOSSUtil;


    public JsonResult list(String id) {
        List<AirData> airDataList = airDataMapper.selectList(Wrappers.<AirData>lambdaQuery()
                .eq(AirData::getMark, MarkEnum.VALID.getCode())
                .eq(AirData::getInspectionId, id));

        return JsonResult.success(airDataList);
    }

    public JsonResult generateTable(String id) {
        User user = CurrentUserUtil.getUserInfo();
        String tenantId = user.getTenantId();
        String userId = user.getId();
        //校验
        JsonResult jsonResult = this.check(id);
        if(0 != jsonResult.getCode()){
            log.info("生成excel表格数据校验失败：{}",jsonResult.getMsg());
            return jsonResult;
        }
        AirDataExport airDataExport = this.checkAirDataExport(id);
        if (ObjectUtil.isNotEmpty(airDataExport)) {
            return JsonResult.success(airDataExport);
        }
        //获取任务名称
        Inspection inspection = inspectionMapper.selectById(id);
        if(ObjectUtil.isNull(inspection)){
            return JsonResult.error(AirDataEnum.INSPECTION_IS_NOT_EXIST.getCode(),AirDataEnum.INSPECTION_IS_NOT_EXIST.getMsg());
        }
        String name = inspection.getName();
        if(StringUtils.isEmpty(name)){
            log.info("对应的任务名称为空");
            throw new ServiceException(ServiceExceptionEnum.FILE_DATA_TIME_IS_ERROR);
        }
        //获取当前任务id下的大气数据
        List<AirData> airDataList = airDataMapper.selectList(Wrappers.<AirData>lambdaQuery()
                .eq(AirData::getMark, MarkEnum.VALID.getCode())
                .eq(AirData::getInspectionId, id));
        if(CollectionUtils.isEmpty(airDataList) || airDataList.size() == 0){
            return JsonResult.error(AirDataEnum.AIR_DATA_IS_NOT_EXIST.getCode(),AirDataEnum.AIR_DATA_IS_NOT_EXIST.getMsg());
        }
        //数据转换
        List<AirDataExcelVo> airDataExcelVoList = new ArrayList<>();
        airDataList.forEach(x->{
            AirDataExcelVo vo = new AirDataExcelVo();
            BeanUtils.copyProperties(x,vo);
            vo.setSo2(x.getSo2());
            vo.setNo2(x.getNo2());
            vo.setO3(x.getO3());
            vo.setPm_2_5(x.getPm25());
            vo.setPm_10(x.getPm10());
            vo.setVocs(x.getVocs());
            vo.setSequence(x.getSequence());
            airDataExcelVoList.add(vo);
        });
        //对列表进行排序
        airDataExcelVoList.stream().sorted(Comparator.comparing(AirDataExcelVo::getSequence)).collect(Collectors.toList());

        String fileName = inspection.getName()+"+"+inspection.getCode()+".xlsx";
        String filePath = UploadFileConfig.uploadFolder + "/data/" + fileName;
        File fd = new File(UploadFileConfig.uploadFolder + "/data");
        //目录是否存在
        if(!fd.exists()){
            fd.mkdirs();
        }
        //生成excel
        JsonResult result = this.easyExcel(airDataExcelVoList,inspection,filePath);
        if (0 != result.getCode()) {
            log.info("导出数据业务：生成excel失败：{}", result.getMsg());
            return result;
        }
        //上传到oss
        String ossUrl = this.uploadOss(filePath,fileName);
        // 删除原文件
        FileUtils.deleteFile(filePath);
        //数据导入记录表中
        Integer count = this.addAirDataExport(id,ossUrl,tenantId,userId);
        if(count <= 0){
            log.info("添加大气数据报告导出记录失败");
        }
        //查询记录表返回结果
        AirDataExport airDataExportResult = airDataExportMapper.selectOne(Wrappers.<AirDataExport>lambdaQuery()
                .eq(AirDataExport::getInspectionId, id)
                .eq(AirDataExport::getMark, MarkEnum.VALID.getCode())
                .eq(AirDataExport::getExportType,"data"));
        return JsonResult.success(airDataExportResult);
    }

    private Integer addAirDataExport(String id, String ossUrl, String tenantId,String userId) {
        AirDataExport airDataExport = new AirDataExport();
        airDataExport.setInspectionId(id);
        airDataExport.setTenantId(tenantId);
        airDataExport.setOssUrl(ossUrl);
        airDataExport.setExportType("data");
        airDataExport.setCreateUser(userId);
        airDataExport.setCreateTime(DateUtils.now());
        int count = airDataExportMapper.insert(airDataExport);
        return count;
    }

    private String uploadOss(String filePath, String fileName) {
        File file = new File(filePath);
        InputStream in = null;
        String ossUrl = "";

        try {
            in = new FileInputStream(file);
            //上传到oss
            aliyunOSSUtil.uploadFile2OSS(in,fileName);
            //通过文件名获取文件完整路径
            ossUrl = aliyunOSSUtil.getFileUrl(fileName);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
        return ossUrl;
    }

    /**
     * 大气报告导出记录表数据校验
     * @param id
     * @return
     */
    private AirDataExport checkAirDataExport(String id) {
        AirDataExport airDataExport = airDataExportMapper.selectOne(Wrappers.<AirDataExport>lambdaQuery()
                .eq(AirDataExport::getInspectionId, id)
                .eq(AirDataExport::getExportType, "data")
                .eq(AirDataExport::getMark, MarkEnum.VALID.getCode()));
        return airDataExport;
    }

    /**
     * 生成excel表格
     * @param voArrayList
     * @param inspection
     * @return
     */
    public JsonResult easyExcel(List<AirDataExcelVo> voArrayList,Inspection inspection,String filePath) {
        log.info("文件输出目录及格式：filePathName={}",filePath);
        List<List<String>> heads = new ArrayList<>();
        String totalName = "项目名称:"+ inspection.getName();
        String[] nameString = SystemConstant.EXCEL_SECOND_NAME;
        for (String excelName : nameString) {
            heads.add(Arrays.asList(totalName,excelName));
        }
        //需要写出的表格（对应实体类）
        try {
            EasyExcel.write(filePath, AirDataExcelVo.class).sheet("大气浓度监测数据").head(heads)
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)) // 简单的列宽策略，列宽20
                    .doWrite(voArrayList);//数据源
        } catch (Exception e) {
            log.info("生成数据导出excel异常");
            throw new RuntimeException(e);
        }
        log.info("开始写入表格中");

        return JsonResult.success();
    }

    private JsonResult check(String id) {
        if(StringUtils.isEmpty(id)){
            return JsonResult.error(AirDataEnum.INSPECTION_ID_IS_NULL.getCode(),AirDataEnum.INSPECTION_ID_IS_NULL.getMsg());
        }
        return JsonResult.success();
    }
}
