package com.zehong.system.service.impl;

import cn.afterturn.easypoi.entity.ImageEntity;
import cn.hutool.core.img.ImgUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zehong.common.exception.CustomException;
import com.zehong.common.utils.DateUtils;
import com.zehong.common.utils.StringUtils;
import com.zehong.common.utils.poi.InspectExportUtil;
import com.zehong.system.domain.*;
import com.zehong.system.mapper.TBusinessMapper;
import com.zehong.system.mapper.TIndustryMapper;
import com.zehong.system.mapper.TTaskInspectExportMapper;
import com.zehong.system.mapper.TUserMapper;
import com.zehong.system.service.ITTaskInspectExportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * 安检单导出Service业务层处理
 * 
 * @author zehong
 * @date 2024-10-16
 */
@Service
public class TTaskInspectExportServiceImpl implements ITTaskInspectExportService 
{
    private static Logger logger = LoggerFactory.getLogger(TTaskInspectServiceImpl.class);
    @Resource
    private TTaskInspectExportMapper tTaskInspectExportMapper;

    @Resource
    private TUserMapper tUserMapper;

    @Resource
    private TBusinessMapper tBusinessMapper;

    @Resource
    private TIndustryMapper tIndustryMapper;

    @Resource
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 查询安检单导出
     * 
     * @param exportId 安检单导出ID
     * @return 安检单导出
     */
    @Override
    public TTaskInspectExport selectTTaskInspectExportById(Long exportId)
    {
        return tTaskInspectExportMapper.selectTTaskInspectExportById(exportId);
    }

    /**
     * 查询安检单导出列表
     * 
     * @param tTaskInspectExport 安检单导出
     * @return 安检单导出
     */
    @Override
    public List<TTaskInspectExport> selectTTaskInspectExportList(TTaskInspectExport tTaskInspectExport)
    {
        return tTaskInspectExportMapper.selectTTaskInspectExportList(tTaskInspectExport);
    }

    /**
     * 新增安检单导出
     * 
     * @param tTaskInspectExport 安检单导出
     * @return 结果
     */
    @Override
    public int insertTTaskInspectExport(TTaskInspectExport tTaskInspectExport)
    {
        tTaskInspectExport.setCreateTime(DateUtils.getNowDate());
        return tTaskInspectExportMapper.insertTTaskInspectExport(tTaskInspectExport);
    }

    /**
     * 修改安检单导出
     * 
     * @param tTaskInspectExport 安检单导出
     * @return 结果
     */
    @Override
    public int updateTTaskInspectExport(TTaskInspectExport tTaskInspectExport)
    {
        return tTaskInspectExportMapper.updateTTaskInspectExport(tTaskInspectExport);
    }

    /**
     * 批量删除安检单导出
     * 
     * @param exportIds 需要删除的安检单导出ID
     * @return 结果
     */
    @Override
    public int deleteTTaskInspectExportByIds(Long[] exportIds)
    {
        return tTaskInspectExportMapper.deleteTTaskInspectExportByIds(exportIds);
    }

    /**
     * 删除安检单导出信息
     * 
     * @param exportId 安检单导出ID
     * @return 结果
     */
    @Override
    public int deleteTTaskInspectExportById(Long exportId)
    {
        return tTaskInspectExportMapper.deleteTTaskInspectExportById(exportId);
    }

    /**
     * 每日安检单导出
     * @param beginTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    @Override
    public void batchExportInspect(String beginTime,String endTime,String taskId){
        Map<String,String> date = new HashMap<>();
        date.put("beginTime",beginTime);
        date.put("endTime",endTime);
        date.put("taskId",taskId);
        List<TTaskInspect> userInspectExportList = tTaskInspectExportMapper.userInspectExport(date);
        if(CollectionUtils.isEmpty(userInspectExportList)) return;
        //居民安检单
        List<TTaskInspect> residentInspectList = userInspectExportList.stream().filter(item -> 1 == item.getType()).collect(Collectors.toList());
        residentExport(residentInspectList);
        //餐饮安检单
        List<TTaskInspect> businessInspectList = userInspectExportList.stream().filter(item -> 2 == item.getType()).collect(Collectors.toList());
        businessExport(businessInspectList);
        //工业季度安检单
        List<TTaskInspect> industryQuarterInspectList = userInspectExportList.stream().filter(item -> 3 == item.getType() && 2 == item.getCheckType()).collect(Collectors.toList());
        industryQuarterExport(industryQuarterInspectList);
        //工业月度安检单
        List<TTaskInspect> industryMonthInspectList = userInspectExportList.stream().filter(item -> 3 == item.getType() && 1 == item.getCheckType()).collect(Collectors.toList());
        industryMonthExport(industryMonthInspectList);
    }

    /**
     * 导出压缩包
     * @param tTaskInspectExport
     * @return
     */
    @Override
    public String exportInspectZip(TTaskInspectExport tTaskInspectExport){
        List<String> fileNameList = tTaskInspectExportMapper.selectFileNameList(tTaskInspectExport);
        if(CollectionUtils.isEmpty(fileNameList)) throw new CustomException("未查询到导出数据");
        return new InspectExportUtil().zipExport(fileNameList,tTaskInspectExport.getFileName());
    }

    /**
     * 居民安检单导出
     * @param residentInspectList
     */
    private void residentExport(List<TTaskInspect> residentInspectList){
        if (CollectionUtils.isEmpty(residentInspectList)) return;
        try{
            List<Map<String,Object>> list = new ArrayList<>();
            for(TTaskInspect inspectExport : residentInspectList){
                Map<String,Object> map = new HashMap<>();
                JSONObject contentJson = (JSONObject) JSON.parse(inspectExport.getContent());
                JSONObject obj = contentJson.getJSONObject("obj");
                for(String key : obj.keySet()){
                    JSONArray valueArr = obj.getJSONObject(key).getJSONArray("valueArr2");
                    for(int i = 0; i < valueArr.size(); i++){
                        map.put(key+i,valueArr.get(i));
                    }
                }
                map.put("dangerNumber",contentJson.getString("dangerNumber"));
                map.put("zgDay",contentJson.getString("zgDay"));
                map.put("qmUrl",contentJson.getString("qmUrl"));
                JSONObject userInfo = contentJson.getJSONObject("userInfo");
                if(null != userInfo){
                    for(String userKey : userInfo.keySet()){
                        map.put(userKey,userInfo.getString(userKey));
                    }
                }
                //user中获取
                TUser user = tUserMapper.selectTUserById(inspectExport.getReceiveId());
                if(null != user){
                    map.put("username",user.getUsername());
                    map.put("usernum",user.getUsernum());
                    map.put("phone",user.getPhone());
                    map.put("address",user.getAddress());
                    map.put("zaoNum",null != user.getDevice() && user.getDevice().contains("0100")? "1" : "0");
                    map.put("guaNum",null != user.getDevice() && user.getDevice().contains("0300")? "1" : "0");
                    map.put("reNum",null != user.getDevice() && user.getDevice().contains("0200")? "1" : "0");
                    map.put("meterType1",null != user.getMeterType() && 1 == user.getMeterType());
                    map.put("meterType2",null != user.getMeterType() && 2 == user.getMeterType());
                    map.put("meterCompany1",null != user.getMeterCompany() && 1 == user.getMeterCompany());
                    map.put("meterCompany2",null != user.getMeterCompany() && 2 == user.getMeterCompany());
                    map.put("meterModel1",null != user.getMeterModel() && 1 == user.getMeterModel());
                    map.put("meterModel2",null != user.getMeterModel() && 2 == user.getMeterModel());
                    map.put("meterModel3",null != user.getMeterModel() && 3 == user.getMeterModel());
                    map.put("direction1",null != user.getDirection() && 1 == user.getDirection());
                    map.put("direction2",null != user.getDirection() && 2 == user.getDirection());
                }
                //安检单中获取
                map.put("rectificationRequirements",inspectExport.getRemark());
                map.put("inspector",inspectExport.getMemberName());
                map.put("currentDate", new SimpleDateFormat("yyyy-MM-dd").format(inspectExport.getCreateTime()));
                map.put("createTime", new SimpleDateFormat("yyyyMMddHHmmss").format(inspectExport.getCreateTime()));
                //日志类组装
                TTaskInspectExport exportLog = new TTaskInspectExport();
                exportLog.setTaskId(inspectExport.getTaskId());
                exportLog.setInspectId(inspectExport.getId());
                exportLog.setInspectTime(inspectExport.getCreateTime());
                exportLog.setReceiveId(inspectExport.getReceiveId());
                exportLog.setMemberId(inspectExport.getMemberId());
                exportLog.setType(inspectExport.getType());
                exportLog.setCreateTime(new Date());
                exportLog.setFileName((String) map.get("username") + map.get("createTime") + "安检单.xlsx");
                map.put("exportLog",exportLog);
                list.add(map);
            }
            InspectExportUtil excelUtil = new InspectExportUtil();
            excelUtil.exportExcel("resident.xlsx",list);
            List<TTaskInspectExport> logList = list.stream().filter(item -> item.containsKey("exportLog"))
                    .flatMap(map -> map.entrySet().stream())
                    .filter(entry -> "exportLog".equals(entry.getKey()))
                    .map(map ->{
                        return (TTaskInspectExport)map.getValue();
                    })
                    .collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(logList)) tTaskInspectExportMapper.batchInsertInspectExport(logList);
        }catch (Exception e){
            logger.error("居民安检导出错误:" + e);
        }
    }

    /**
     * 餐饮安检单导出
     * @param businessInspectList
     */
    private void businessExport(List<TTaskInspect> businessInspectList) {
        if (CollectionUtils.isEmpty(businessInspectList)) return;
        try{
            List<Map<String,Object>> mapList = new Vector<>();
            Future<?>[] futures = new Future[businessInspectList.size()];
            for(int index = 0; index < businessInspectList.size(); index++){
                int finalIndex = index;
                futures[index] = threadPoolTaskExecutor.submit(()->{
                    try {
                        Map<String,Object> map = new HashMap<>();
                        JSONObject contentJson = (JSONObject) JSON.parse(businessInspectList.get(finalIndex).getContent());
                        JSONObject obj = contentJson.getJSONObject("obj");
                        for(String key : obj.keySet()){
                            JSONArray valueArr = obj.getJSONObject(key).getJSONArray("valueArr2");
                            for(int i = 0; i < valueArr.size(); i++){
                                map.put(key+i,(boolean)valueArr.get(i)?"\u2611":"\u2610");
                            }
                        }
                        if(StringUtils.isNotEmpty(contentJson.getString("qmUrl"))){
                            //Image image = ImgUtil.rotate(ImageIO.read(new URL(contentJson.getString("qmUrl"))), -90);
                            byte[] bytes = ImgUtil.toBytes(InspectExportUtil.rotateImage(contentJson.getString("qmUrl"),-90),"png");
                            ImageEntity imageEntity = new ImageEntity(bytes,100,40);
                            map.put("qmUrl",imageEntity);
                        }

                        map.put("dangerNumber",contentJson.getString("dangerNumber"));
                        map.put("zgDay",contentJson.getString("zgDay"));
                        JSONObject userInfo = contentJson.getJSONObject("userInfo");
                        if(null != userInfo){
                            for(String userKey : userInfo.keySet()){
                                map.put(userKey,userInfo.getString(userKey));
                            }
                        }
                        //user中获取
                        TBusiness businessInfo = tBusinessMapper.selectTBusinessById(businessInspectList.get(finalIndex).getReceiveId());
                        if(null != businessInfo){
                            map.put("company",businessInfo.getCompany());
                            map.put("contract",businessInfo.getContract());
                            map.put("address",businessInfo.getAddress());
                            map.put("usernum",businessInfo.getUsernum());
                            map.put("username",businessInfo.getUsername());
                            map.put("phone",businessInfo.getPhone());
                            map.put("meterType1",null != businessInfo.getMeterType() && 1 == businessInfo.getMeterType()?"\u2611":"\u2610");
                            map.put("meterType2",null != businessInfo.getMeterType() && 2 == businessInfo.getMeterType()?"\u2611":"\u2610");
                            map.put("meterModel1",null != businessInfo.getMeterModel() && 1==businessInfo.getMeterModel()?"\u2611":"\u2610");
                            map.put("meterModel2",null != businessInfo.getMeterModel() && 2==businessInfo.getMeterModel()?"\u2611":"\u2610");
                            map.put("meterModel3",null != businessInfo.getMeterModel() && 3==businessInfo.getMeterModel()?"\u2611":"\u2610");
                            map.put("meterCompany1",null != businessInfo.getMeterCompany() && 1==businessInfo.getMeterCompany()?"\u2611":"\u2610");
                            map.put("meterCompany2",null != businessInfo.getMeterCompany() && 2==businessInfo.getMeterCompany()?"\u2611":"\u2610");
                            map.put("direction1",null != businessInfo.getDirection() && 1==businessInfo.getDirection()?"\u2611":"\u2610");
                            map.put("direction2",null != businessInfo.getDirection() && 1==businessInfo.getDirection()?"\u2611":"\u2610");
                            String device = businessInfo.getDevice();
                            if(StringUtils.isNotEmpty(device)){
                                JSONObject deviceObj = JSON.parseObject(device);
                                map.put("bothEyes",deviceObj.getString("bothEyes"));
                                map.put("singleEyes",deviceObj.getString("singleEyes"));
                                map.put("manyEyes",deviceObj.getString("manyEyes"));
                                map.put("cauldron",deviceObj.getString("cauldron"));
                                map.put("civil",deviceObj.getString("civil"));
                                map.put("barbecue",deviceObj.getString("barbecue"));
                                map.put("lowSoup",deviceObj.getString("lowSoup"));
                                map.put("clayPot",deviceObj.getString("clayPot"));
                                map.put("dwarf",deviceObj.getString("dwarf"));
                                map.put("oven",deviceObj.getString("oven"));
                                map.put("steamer",deviceObj.getString("steamer"));
                                map.put("barrel",deviceObj.getString("barrel"));
                                map.put("wall",deviceObj.getString("wall"));
                            }
                        }

                        //安检单中取
                        map.put("inspector",businessInspectList.get(finalIndex).getMemberName());
                        map.put("currentDate", new SimpleDateFormat("yyyy-MM-dd").format(businessInspectList.get(finalIndex).getCreateTime()));
                        map.put("createTime", new SimpleDateFormat("yyyyMMddHHmmss").format(businessInspectList.get(finalIndex).getCreateTime()));
                        //日志类组装
                        TTaskInspectExport exportLog = new TTaskInspectExport();
                        exportLog.setTaskId(businessInspectList.get(finalIndex).getTaskId());
                        exportLog.setInspectId(businessInspectList.get(finalIndex).getId());
                        exportLog.setInspectTime(businessInspectList.get(finalIndex).getCreateTime());
                        exportLog.setReceiveId(businessInspectList.get(finalIndex).getReceiveId());
                        exportLog.setMemberId(businessInspectList.get(finalIndex).getMemberId());
                        exportLog.setType(businessInspectList.get(finalIndex).getType());
                        exportLog.setCreateTime(new Date());
                        exportLog.setFileName((String) map.get("company") + map.get("createTime") + "安检单.docx");
                        map.put("exportLog",exportLog);
                        mapList.add(map);
                    } catch (Exception e) {
                        logger.error("餐饮参数组装失败:" + e);
                    }

                });
            }

            // 等待所有任务完成
            for (Future<?> future : futures) {
                // 这将阻塞直到每个Future表示的任务完成。
                future.get();
            }

            InspectExportUtil excelUtil = new InspectExportUtil();
            excelUtil.exportEasyWord("business-easy.docx",mapList);
            List<TTaskInspectExport> logList = mapList.stream().filter(item -> item.containsKey("exportLog"))
                    .flatMap(map -> map.entrySet().stream())
                    .filter(entry -> "exportLog".equals(entry.getKey()))
                    .map(map ->{
                        return (TTaskInspectExport)map.getValue();
                    })
                    .collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(logList)) tTaskInspectExportMapper.batchInsertInspectExport(logList);

        }catch (Exception e){
            logger.error("餐饮安检导出错误:" + e.getMessage());
        }


    }


    /**
     * 工业季度安检单导出
     * @param industryQuarterInspectList
     */
    private void industryQuarterExport(List<TTaskInspect> industryQuarterInspectList){
        if (CollectionUtils.isEmpty(industryQuarterInspectList)) return;
        try{
            List<Map<String,Object>> list = new ArrayList<>();
            for(TTaskInspect inspectExport : industryQuarterInspectList){
                Map<String,Object> map = new HashMap<>();
                JSONObject contentJson = (JSONObject) JSON.parse(inspectExport.getContent());
                JSONObject obj = contentJson.getJSONObject("obj");
                for(String key : obj.keySet()){
                    JSONArray valueArr = obj.getJSONObject(key).getJSONArray("valueArr2");
                    for(int i = 0; i < valueArr.size(); i++){
                        map.put(key+i,valueArr.get(i));
                    }
                }
                map.put("dangerNumber",contentJson.getString("dangerNumber"));
                map.put("qmUrl",contentJson.getString("qmUrl"));
                if(!map.containsKey("famanz0")){
                    map.put("famenz0",true);
                    map.put("famenz1",false);
                }
                //user中获取
                TIndustry user = tIndustryMapper.selectTIndustryById(inspectExport.getReceiveId());
                if(null != user){
                    map.put("username",user.getCompany());
                }
                //安检单中获取
                map.put("remarks",inspectExport.getRemark());
                map.put("inspector",inspectExport.getMemberName());
                map.put("currentDate", new SimpleDateFormat("yyyy-MM-dd").format(inspectExport.getCreateTime()));
                map.put("createTime", new SimpleDateFormat("yyyyMMddHHmmss").format(inspectExport.getCreateTime()));
                //日志类组装
                TTaskInspectExport exportLog = new TTaskInspectExport();
                exportLog.setTaskId(inspectExport.getTaskId());
                exportLog.setInspectId(inspectExport.getId());
                exportLog.setInspectTime(inspectExport.getCreateTime());
                exportLog.setReceiveId(inspectExport.getReceiveId());
                exportLog.setMemberId(inspectExport.getMemberId());
                exportLog.setType(inspectExport.getType());
                exportLog.setCreateTime(new Date());
                exportLog.setFileName((String) map.get("username") + map.get("createTime") + "安检单.xlsx");
                map.put("exportLog",exportLog);
                list.add(map);
            }
            InspectExportUtil excelUtil = new InspectExportUtil();
            excelUtil.exportExcel("quarter.xlsx",list);
            List<TTaskInspectExport> logList = list.stream().filter(item -> item.containsKey("exportLog"))
                    .flatMap(map -> map.entrySet().stream())
                    .filter(entry -> "exportLog".equals(entry.getKey()))
                    .map(map ->{
                        return (TTaskInspectExport)map.getValue();
                    })
                    .collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(logList)) tTaskInspectExportMapper.batchInsertInspectExport(logList);
        }catch (Exception e){
            logger.error("工业季度安检导出错误:" + e.getMessage());
        }
    }


    /**
     * 工业季度安检单导出
     * @param industryMonthInspectList
     */
    private void industryMonthExport(List<TTaskInspect> industryMonthInspectList){
        if (CollectionUtils.isEmpty(industryMonthInspectList)) return;
        try{
            List<Map<String,Object>> mapList = new Vector<>();
            Future<?>[] futures = new Future[industryMonthInspectList.size()];
            for(int index = 0; index < industryMonthInspectList.size(); index++){
                int finalIndex = index;
                futures[index] = threadPoolTaskExecutor.submit(()->{
                    try {
                        Map<String,Object> map = new HashMap<>();
                        JSONObject contentJson = (JSONObject) JSON.parse(industryMonthInspectList.get(finalIndex).getContent());
                        JSONObject obj = contentJson.getJSONObject("obj");
                        for(String key : obj.keySet()){
                            JSONArray valueArr = obj.getJSONObject(key).getJSONArray("valueArr2");
                            for(int i = 0; i < valueArr.size(); i++){
                                map.put(key+i,(boolean)valueArr.get(i)?"\u2611":"\u2610");
                            }
                        }
                        if(StringUtils.isNotEmpty(contentJson.getString("qmUrl"))){
                            //Image image = ImgUtil.rotate(ImageIO.read(new URL(contentJson.getString("qmUrl"))), -90);
                            byte[] bytes = ImgUtil.toBytes(InspectExportUtil.rotateImage(contentJson.getString("qmUrl"),-90),"png");
                            ImageEntity imageEntity = new ImageEntity(bytes,100,20);
                            map.put("qmUrl",imageEntity);
                        }

                        map.put("dangerNumber",contentJson.getString("dangerNumber"));
                        //user中获取
                        TIndustry info = tIndustryMapper.selectTIndustryById(industryMonthInspectList.get(finalIndex).getReceiveId());
                        if(null != info){
                            map.put("company",info.getCompany());
                        }

                        //安检单中取
                        map.put("inspector",industryMonthInspectList.get(finalIndex).getMemberName());
                        map.put("currentDate", new SimpleDateFormat("yyyy-MM-dd").format(industryMonthInspectList.get(finalIndex).getCreateTime()));
                        map.put("createTime", new SimpleDateFormat("yyyyMMddHHmmss").format(industryMonthInspectList.get(finalIndex).getCreateTime()));

                        //日志类组装
                        TTaskInspectExport exportLog = new TTaskInspectExport();
                        exportLog.setTaskId(industryMonthInspectList.get(finalIndex).getTaskId());
                        exportLog.setInspectId(industryMonthInspectList.get(finalIndex).getId());
                        exportLog.setInspectTime(industryMonthInspectList.get(finalIndex).getCreateTime());
                        exportLog.setReceiveId(industryMonthInspectList.get(finalIndex).getReceiveId());
                        exportLog.setMemberId(industryMonthInspectList.get(finalIndex).getMemberId());
                        exportLog.setType(industryMonthInspectList.get(finalIndex).getType());
                        exportLog.setCreateTime(new Date());
                        exportLog.setFileName((String) map.get("company") + map.get("createTime") + "安检单.docx");
                        map.put("exportLog",exportLog);
                        mapList.add(map);
                    } catch (Exception e) {
                        logger.error("工业月度安检单参数组装失败:" + e);
                    }

                });
            }

            // 等待所有任务完成
            for (Future<?> future : futures) {
                // 这将阻塞直到每个Future表示的任务完成。
                future.get();
            }

            InspectExportUtil excelUtil = new InspectExportUtil();
            excelUtil.exportEasyWord("month.docx",mapList);
            List<TTaskInspectExport> logList = mapList.stream().filter(item -> item.containsKey("exportLog"))
                    .flatMap(map -> map.entrySet().stream())
                    .filter(entry -> "exportLog".equals(entry.getKey()))
                    .map(map ->{
                        return (TTaskInspectExport)map.getValue();
                    })
                    .collect(Collectors.toList());
            if(!CollectionUtils.isEmpty(logList)) tTaskInspectExportMapper.batchInsertInspectExport(logList);

        }catch (Exception e){
            logger.error("工业月度安检导出错误:" + e.getMessage());
        }
    }

}
