package com.iformall.controller.mem;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.afterturn.easypoi.handler.impl.ExcelDataHandlerDefaultImpl;
import cn.afterturn.easypoi.handler.inter.IExcelDataHandler;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.iformall.domain.po.MallUserInfo;
import com.iformall.domain.po.WxMerchant;
import com.iformall.domain.po.WxTags;
import com.iformall.domain.vo.CUserBaseInfoT;
import com.iformall.domain.vo.WxBillExcelTemplate;
import com.iformall.domain.vo.WxBillExcelTemplateOther;
import com.iformall.enums.EnumMerchantStatus;
import com.iformall.mapper.WxMerchantMapper;
import com.iformall.service.WxBillAllService;
import com.iformall.service.WxCUserBasicInfoService;
import com.iformall.service.WxTagsService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.UnknownSessionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author gongbiao
 */
@Component
public class ImportTemplateTask {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private WxCUserBasicInfoService wxCUserBasicInfoService;

    @Autowired
    private WxTagsService wxTagsService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    private WxBillAllService wxBillAllService;

    @Autowired
    private WxMerchantMapper wxMerchantMapper;


    @Async
    public void importBillData(File file, MallUserInfo user, String importKey, String tenantId) {
        ImportParams params = new ImportParams();
        // 需要验证
        params.setImportFields(new String[]{"商户名*", "费用类型*", "费用属性*", "费用所属期-开始时间*", "费用所属期-结束时间*", "收款金额(元)*", "收款日期*", "截止缴款日*", "收款方式"});
        params.setNeedVerify(true);

        ExcelImportResult<WxBillExcelTemplate> datalist = null;

        try {
            datalist = ExcelImportUtil.importExcelMore(file, WxBillExcelTemplate.class, params);
        } catch (Exception e) {
            set_redis_value(importKey, "1", "0", "0", "1", true);
            logger.error(e.getMessage());
            // 删除缓存文件
            file.delete();
            return;
        }
        // 删除缓存文件
        file.delete();

        if (datalist == null) {
            logger.error("导入模板失败: 模板数据解析失败");
            set_redis_value(importKey, "1", "0", "0", "1", true);
            return;
        }

        List<WxBillExcelTemplate> successList = datalist.getList();
        List<WxBillExcelTemplate> failList = datalist.getFailList();

        //此处判断商户是否存在
        //1 过滤重复商户名
        Set<String> merchantSet = successList.parallelStream().filter(s -> StringUtils.isNotEmpty(s.getMerchantName()))
                .map(s -> StringUtils.trim(s.getMerchantName()))
                .collect(Collectors.toSet());
        //2 查询商户名是否存在
        Map<String, WxMerchant> merchantMap = new HashMap<>();
        merchantSet.parallelStream().forEach(merchantName -> {
            WxMerchant wxMerchantQuery = new WxMerchant();
            wxMerchantQuery.setTenantId(tenantId);
            wxMerchantQuery.setName(merchantName);
            wxMerchantQuery.setStatus(EnumMerchantStatus.VALID.getCode());
            WxMerchant wxMerchant = wxMerchantMapper.selectOne(new QueryWrapper(wxMerchantQuery));
            if (wxMerchant != null) {
                merchantMap.put(merchantName, wxMerchant);
            }
        });
        //3 计失败条数
        List<WxBillExcelTemplate> billSuccessList = new ArrayList<>();
        successList.parallelStream().forEach(s -> {
            if (StringUtils.isNotEmpty(s.getMerchantName()) && null != s.getBillType()
                    && StringUtils.isNotEmpty(s.getBillAttr()) && null != s.getStarttime()
                    && null != s.getEndtime() && StringUtils.isNotEmpty(s.getPayStr())
                    && null != s.getPayDate() && null != s.getReceiveDate()) {
                WxMerchant wxMerchant = merchantMap.get(s.getMerchantName());
                if (wxMerchant != null) {
                    Long merchantId = wxMerchant.getId();
                    if (merchantId != null) {
                        s.setMerchantId(merchantId);
                        Integer type = wxMerchant.getType();
                        s.setMerchantType(type);
                        billSuccessList.add(s);
                    }
                }
            }
        });
        int billSuccessSize = billSuccessList.size();
        int successSize = successList.size();
        int failSize = failList.size();
        int total = successSize + failSize;
        int failCount = successSize - billSuccessSize;
        int all_success = billSuccessSize;
        int all_fail = failSize + failCount;

        logger.info("验证通过的数量: " + billSuccessSize);
        logger.info("验证未通过的数量: " + failSize);

        //添加到redis里
        set_redis_value(importKey, "" + total, "" + all_success, "0", "" + all_fail, total == all_fail);

        if (billSuccessSize > 0) {
            try {
                billSuccessList.stream().forEach(bill -> {
                    try {
                        wxBillAllService.importBill(tenantId, importKey, bill, user);
                    } catch (UnknownSessionException ue) {
                        logger.error("session :" + ue.getMessage());
                    }
                });
            } catch (Exception e) {
                set_redis_value(importKey, "1", "0", "0", "1", true);
                e.printStackTrace();
                logger.error("导入模板失败:" + e.getMessage());
            }
        }
    }

    public void importBillDataOther(File file, MallUserInfo user, String importKey, String tenantId) {
        ImportParams params = new ImportParams();
        // 需要验证
        params.setImportFields(new String[]{"商户名*", "费用类型*", "费用名称*", "费用所属期-开始时间*", "费用所属期-结束时间*", "实际应收金额(元)*", "收款金额(元)*", "收款日期", "截止缴款日*", "收款方式"});
        params.setNeedVerify(true);

        ExcelImportResult<WxBillExcelTemplateOther> datalist = null;

        try {
            datalist = ExcelImportUtil.importExcelMore(file, WxBillExcelTemplateOther.class, params);
        } catch (Exception e) {
            set_redis_value(importKey, "1", "0", "0", "1", true);
            logger.error(e.getMessage());
            // 删除缓存文件
            file.delete();
            return;
        }
        // 删除缓存文件
        file.delete();

        if (datalist == null) {
            logger.error("导入模板失败: 模板数据解析失败");
            set_redis_value(importKey, "1", "0", "0", "1", true);
            return;
        }

        List<WxBillExcelTemplateOther> successList = datalist.getList();
        List<WxBillExcelTemplateOther> failList = datalist.getFailList();

        //此处判断商户是否存在
        //1 过滤重复商户名
        Set<String> merchantSet = successList.parallelStream().filter(s -> StringUtils.isNotEmpty(s.getMerchantName()))
                .map(s -> StringUtils.trim(s.getMerchantName()))
                .collect(Collectors.toSet());
        //2 查询商户名是否存在
        Map<String, WxMerchant> merchantMap = new HashMap<>();
        merchantSet.parallelStream().forEach(merchantName -> {
            WxMerchant wxMerchantQuery = new WxMerchant();
            wxMerchantQuery.setTenantId(tenantId);
            wxMerchantQuery.setName(merchantName);
            wxMerchantQuery.setStatus(EnumMerchantStatus.VALID.getCode());
            WxMerchant wxMerchant = wxMerchantMapper.selectOne(new QueryWrapper(wxMerchantQuery));
            if (wxMerchant != null) {
                merchantMap.put(merchantName, wxMerchant);
            }
        });
        //3 计失败条数
        List<WxBillExcelTemplateOther> billSuccessList = new ArrayList<>();
        successList.parallelStream().forEach(s -> {
            boolean flag = StringUtils.isNotEmpty(s.getMerchantName()) && null != s.getBillType()
                    && StringUtils.isNotEmpty(s.getBillAttr()) && null != s.getStarttime()
                    && null != s.getEndtime() && StringUtils.isNotEmpty(s.getPayStr())
                    && null != s.getReceiveDate() && StringUtils.isNotEmpty(s.getReceivePayStr());
            if (flag) {
                double pay = new BigDecimal(s.getPayStr()).doubleValue();
                //付款大于0且付款日期不为空说明是更新账单 或者 付款为0且付款日期为空是新增账单 满足其一即可继续
                flag = (pay > 0 && null != s.getPayDate()) || (pay == 0 && null == s.getPayDate());
                if (flag) {
                    WxMerchant wxMerchant = merchantMap.get(s.getMerchantName());
                    if (wxMerchant != null) {
                        Long merchantId = wxMerchant.getId();
                        if (merchantId != null) {
                            s.setMerchantId(merchantId);
                            Integer type = wxMerchant.getType();
                            s.setMerchantType(type);
                            billSuccessList.add(s);
                        }
                    }
                }
            }
        });
        int billSuccessSize = billSuccessList.size();
        int successSize = successList.size();
        int failSize = failList.size();
        int total = successSize + failSize;
        int failCount = successSize - billSuccessSize;
        int all_success = billSuccessSize;
        int all_fail = failSize + failCount;

        logger.info("验证通过的数量: " + billSuccessSize);
        logger.info("验证未通过的数量: " + failSize);

        //添加到redis里
        set_redis_value(importKey, "" + total, "" + all_success, "0", "" + all_fail, total == all_fail);

        if (billSuccessSize > 0) {
            try {
                billSuccessList.stream().forEach(bill -> {
                    try {
                        wxBillAllService.importBillOther(tenantId, importKey, bill, user);
                    } catch (UnknownSessionException ue) {
                        logger.error("session :" + ue.getMessage());
                    }
                });
            } catch (Exception e) {
                set_redis_value(importKey, "1", "0", "0", "1", true);
                e.printStackTrace();
                logger.error("导入模板失败:" + e.getMessage());
            }
        }
    }

    private class UserExcelHandler extends ExcelDataHandlerDefaultImpl<CUserBaseInfoT> {
        @Override
        public Object importHandler(CUserBaseInfoT obj, String name, Object value) {
            if (value == null) {
                value = "";
            }
            System.out.println(name + " + " + value.toString());
            return super.importHandler(obj, name, value);
        }

    }

    private void set_redis_value(String importKey, String allCount, String allSuccessCount, String processCount, String failCount, boolean fail) {
        stringRedisTemplate.opsForHash().put(importKey, "allCount", allCount);
        stringRedisTemplate.opsForHash().put(importKey, "allSuccessCount", allSuccessCount);
        stringRedisTemplate.opsForHash().put(importKey, "processCount", processCount);
        stringRedisTemplate.opsForHash().put(importKey, "failCount", failCount);
        if (fail) {
            stringRedisTemplate.expire(importKey, 10, TimeUnit.SECONDS);
        }
    }

    @Async
    public void importMemberData(File file, MallUserInfo user, String importKey, String tenantId) {
        ImportParams params = new ImportParams();
        // 需要验证
        params.setImportFields(new String[]{"姓名", "性别", "手机号*", "微信昵称", "学历", "生日", "地址", "上次活跃时间", "注册时间", "标签", "成长值", "积分"});
        IExcelDataHandler<CUserBaseInfoT> handler = new ImportTemplateTask.UserExcelHandler();
        handler.setNeedHandlerFields(new String[]{"手机号*"});
        params.setNeedVerify(true);

        ExcelImportResult<CUserBaseInfoT> datalist = null;

        try {
            datalist = ExcelImportUtil.importExcelMore(file, CUserBaseInfoT.class, params);
        } catch (Exception e) {
            set_redis_value(importKey, "1", "0", "0", "1", true);
            logger.error(e.getMessage());
            // 删除缓存文件
            file.delete();
            return;
        }
        // 删除缓存文件
        file.delete();

        if (datalist == null) {
            logger.error("导入模板失败: 模板数据解析失败");
            set_redis_value(importKey, "1", "0", "0", "1", true);
            return;
        }

        List<CUserBaseInfoT> successList = datalist.getList();
        List<CUserBaseInfoT> failList = datalist.getFailList();

        logger.info("验证通过的数量: " + successList.size());
        logger.info("验证未通过的数量: " + failList.size());

        int total = successList.size() + failList.size();
        int all_success = successList.size();
        int all_fail = failList.size();

        //添加到redis里
        set_redis_value(importKey, "" + total, "" + all_success, "0", "" + all_fail, total == all_fail);

        if (successList.size() > 0) {
            WxTags wxTagsQ = new WxTags();
            List<WxTags> tagList = wxTagsService.findList(wxTagsQ);

            try {
                successList.parallelStream().forEach(uBase -> {
                    try {
                        wxCUserBasicInfoService.importOneMem(tenantId, importKey, tagList, uBase, user);
                    } catch (UnknownSessionException ue) {
                        logger.error("session :" + ue.getMessage());
                    }
                });
            } catch (Exception e) {
                set_redis_value(importKey, "1", "0", "0", "1", true);
                e.printStackTrace();
                logger.error("导入模板失败:" + e.getMessage());
            }
        }
    }


}
