package com.dxhy.core.thread;


import com.dxhy.api.model.excelExport.TDxExcelExportlog;
import com.dxhy.core.service.singletable.IExcelExportlogService;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.dxhy.api.model.config.Business;
import com.dxhy.api.model.excelExport.TDxExcelExportlog;
import com.dxhy.common.service.impl.TabulateRedisServiceImpl;
import com.dxhy.common.util.ExcelPoiUtil;
import com.dxhy.common.util.ExceptionUtil;
import com.dxhy.common.util.StringHelper;
import com.dxhy.common.utils.DateUtils;
import com.dxhy.core.feign.IFeginWebsocket;
import com.dxhy.core.model.FpRzRespVO;
import com.dxhy.common.rabbitmq.RabbitMqSender;
import com.dxhy.core.service.export.RzFpxxService;
import com.dxhy.core.service.singletable.IExcelExportlogService;
import com.dxhy.core.util.JsonResponseUtils;
import com.dxhy.oss.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 * @author kangzq 认证发票导出 2019年5月6日
 */

@SuppressWarnings("AlibabaMethodTooLong")
@Slf4j

public class RzFpxxExportThread extends BaseThread {

    /**
     * 默认要导出第几页的数据
     */
    private final int default_curr = 1;
    /**
     * 默认每页导出多少条数据
     */
    private final int default_size = 5000;
    /**
     * 文件名前缀
     */
    private final String fileNamePrefix = "rzfpxxList";
    /**
     * 文件名后缀
     */
    private final String fileNameSurfix = ".xlsx";
    /**
     * 文件名中间分隔符
     */
    private final String fileSplit = "_";
    /**
     * excel的标题
     */
    private final String title = "认证查询";
    /**
     * 导出excel的列名
     */
    private String[] titleColumns =
        {"序号", "发票代码", "发票号码", "发票类型", "开票日期", "购方名称", "购方税号", "销方名称", "销方税号", "金额", "税额", "抵扣税额", "发票状态", "签收状态",
            "签收日期", "签收方式", "签收人", "认证时间", "认证状态", "认证处理状态", "认证类型", "认证人", "税款所属期", "撤销认证处理状态", "业务单元"};

    private final IExcelExportlogService exportLogService;

    private final List<TDxExcelExportlog> exportLogs;

    private final RzFpxxService rzFpxxService;

    private final FileService fileService;

    private final RabbitMqSender sender;
    private final TabulateRedisServiceImpl tabulateRedisService;

    public RzFpxxExportThread(IExcelExportlogService exportLogService, List<TDxExcelExportlog> exportLogs,
                              RzFpxxService rzFpxxService, FileService fileService, RabbitMqSender sender, IFeginWebsocket feginWebsocket,
                              TabulateRedisServiceImpl tabulateRedisService) {

        this.exportLogService = exportLogService;
        this.exportLogs = exportLogs;
        this.rzFpxxService = rzFpxxService;
        this.fileService = fileService;
        this.sender = sender;
        this.feginWebsocket = feginWebsocket;
        this.tabulateRedisService = tabulateRedisService;
    }

    private final IFeginWebsocket feginWebsocket;

    @Override
    public void run() {
        for (TDxExcelExportlog exportLog : exportLogs) {
            // 日志表主键
            Long id = exportLog.getId();
            String userid = exportLog.getUserAccount();
            String userName = exportLog.getUserName();
            // 导出条件
            String condition = exportLog.getConditions();
            // 数据源名称
            String dbName = exportLog.getDbName();
            if (StringHelper.isBlank(dbName)) {
                dbName = "";
            }
            String createDate = DateUtils.dateToStrLong(exportLog.getCreateDate());

            JSONObject msg = new JSONObject();

            // 捕获异常，防止某一条日志导出出错，影响其它日志的导出
            try {
                exportLogService.updateStart(id, dbName);

                // 应该保存的参数
                JSONObject prams = JSONObject.parseObject(condition);
                String gfsh = prams.getString("gfsh");
                String kpksrq = prams.getString("kpksrq");
                String kpjsrq = prams.getString("kpjsrq");
                String invoiceType = prams.getString("invoiceType");
                String invoiceSource = prams.getString("invoiceSource");
                String qszt = prams.getString("qszt");
                String qsksrq = prams.getString("qsksrq");
                String qsjsrq = prams.getString("qsjsrq");
                String rzzt = prams.getString("rzzt");
                String rzksrq = prams.getString("rzksrq");
                String rzjsrq = prams.getString("rzjsrq");
                String skssq = prams.getString("skssq");
                String invoiceStatus = prams.getString("invoiceStatus");
                String qsfs = prams.getString("qsfs");
                String rzclzt = prams.getString("rzclzt");
                String invoiceNo = prams.getString("invoiceNo");
                String xfmc = prams.getString("xfmc");
                String rzlx = prams.getString("rzlx");
                String rzhr = prams.getString("rzhr");
                String company = prams.getString("company");
                String menuId = prams.getString("menuId");
                JSONObject jsonObject = tabulateRedisService.getTabulateExcel(company, menuId);
                List<Business> businesses = (List<Business>)prams.get("business");
                String inAccountStatus = prams.getString("inAccountStatus");
                // 参数转换为需要的形式
                Map<String, Object> pramsMap = new HashMap<>(30);
                pramsMap.put("dbName", dbName);
                pramsMap.put("business", businesses);

                pramsMap.put("paymentDateStart", prams.getString("paymentDateStart"));
                pramsMap.put("paymentDateEnd", prams.getString("paymentDateEnd"));
                pramsMap.put("paymentStatus", prams.getString("paymentStatus"));
                pramsMap.put("voucherNumber", prams.getString("voucherNumber"));

                List<String> gfshList = new ArrayList<>();
                if (!StringHelper.isBlank(gfsh)) {
                    gfshList = StringHelper.stringToList(gfsh);
                    pramsMap.put("gfsh", gfshList);
                } else {
                    pramsMap.put("gfsh", gfshList);
                }
//                pramsMap.put("kpksrq", DateUtils.getMorning(DateUtils.strToDate(kpksrq)));
                pramsMap.put("kpksrq", kpksrq);
//                pramsMap.put("kpjsrq", DateUtils.getNight(DateUtils.strToDate(kpjsrq)));
                pramsMap.put("kpjsrq", kpjsrq);
                if (!"99".equals(invoiceType) && StringUtils.isNotBlank(invoiceType)) {
                    pramsMap.put("invoiceType", invoiceType);
                } else {
                    pramsMap.put("invoiceType", "");
                }
                if (invoiceSource != null) {
                    if (!"99".equals(invoiceSource)) {
                        pramsMap.put("invoiceSource", invoiceSource);
                    }
                }
                pramsMap.put("businessCode", "99");
                if (!"99".equals(qszt) && StringUtils.isNotBlank(qszt)) {
                    pramsMap.put("qszt", qszt);
                    if ("1".equals(qszt)) {
                        if (StringUtils.isNotBlank(qsksrq)) {
                            pramsMap.put("qsksrq", qsksrq);
                        }
                        if (StringUtils.isNotBlank(qsjsrq)) {
                            pramsMap.put("qsjsrq", qsjsrq);
                        }
                        if (StringUtils.isNotBlank(qsfs) && !"99".equals(qsfs)) {
                            pramsMap.put("qsfs", qsfs);
                        }
                        pramsMap.put("businessCode", prams.getString("businessCode"));
                    }
                } else {
                    pramsMap.put("qszt", "");
                }
                if (!"99".equals(rzzt) && StringUtils.isNotBlank(rzzt)) {
                    pramsMap.put("rzzt", rzzt);
                    if ("1".equals(rzzt) || "2".equals(rzzt)) {
                        if (StringUtils.isNotBlank(rzksrq)) {
                            pramsMap.put("rzksrq", rzksrq);
                        }
                        if (StringUtils.isNotBlank(rzjsrq)) {
                            pramsMap.put("rzjsrq", rzjsrq);
                        }
                        if (StringUtils.isNotBlank(skssq)) {
                            pramsMap.put("skssq", skssq);
                        }
                    }
                } else {
                    pramsMap.put("rzzt", "");
                }
                if (StringUtils.isNotBlank(invoiceStatus) && !"99".equals(invoiceStatus)) {
                    pramsMap.put("invoiceStatus", invoiceStatus);
                }
                if (!"99".equals(rzclzt) && StringUtils.isNotBlank(rzclzt)) {
                    pramsMap.put("rzclzt", rzclzt);
                } else {
                    pramsMap.put("rzclzt", "");
                }
                if (!StringUtils.isBlank(invoiceNo)) {
                    if(invoiceNo.length()==8){
                        pramsMap.put("invoiceNo", invoiceNo);
                    }else {
                        pramsMap.put("eleInvoiceNo", invoiceNo);
                    }
                }
                pramsMap.put("xfmc", xfmc);
                if (StringUtils.isNotBlank(rzlx) && !"99".equals(rzlx)) {
                    pramsMap.put("rzlx", rzlx);
                }
                if (StringUtils.isNotBlank(rzhr)) {
                    pramsMap.put("rzhr", rzhr);
                }
                pramsMap.put("inAccountStatus", inAccountStatus);
                pramsMap.put("company", company);
                pramsMap.put("qsr", prams.getString("qsr"));
                if (StringUtils.isNotBlank(inAccountStatus)) {
                    titleColumns = new String[] {"序号", "打款状态", "发票代码", "发票号码", "发票类型", "开票日期", "购方名称", "购方税号", "销方名称",
                        "销方税号", "金额", "税额", "抵扣税额", "发票状态", "签收状态", "签收日期", "签收方式", "签收人", "认证时间", "认证状态", "认证处理状态",
                        "认证类型", "认证人", "税款所属期", "撤销认证处理状态", "业务单元"};
                }
                if ("1".equals(prams.getString("payment"))) {
                    titleColumns = new String[] {"序号", "发票代码", "发票号码", "发票类型", "开票日期", "购方名称", "购方税号", "销方名称", "销方税号",
                        "金额", "税额", "抵扣税额", "发票状态", "签收状态", "签收日期", "签收方式", "签收人", "认证时间", "认证状态", "认证处理状态", "认证类型",
                        "认证人", "税款所属期", "撤销认证处理状态", "付款状态", "付款时间"};
                }
                // 导出文件名
                StringBuilder ftpFileName = new StringBuilder();
                ftpFileName.append(userid);
                ftpFileName.append(fileSplit);
                ftpFileName.append(fileNamePrefix);
                ftpFileName.append(fileSplit);
                ftpFileName.append(DateUtils.getStringDateShort());
                ftpFileName.append(fileSplit);
                ftpFileName.append((new Date()).getTime());
                ftpFileName.append(fileNameSurfix);

                // 本地文件存储路径
                StringBuilder excelFile = new StringBuilder();
                excelFile.append(fileService.getLocalPathDefault());
                excelFile.append(ftpFileName.toString());

                // 递归导出数据到excel
                this.cicleExport(pramsMap, default_curr, excelFile.toString(), jsonObject);

                // FTP文件存储路径
                String[] toDay = DateUtil.today().split("-");
                String ftpFilePath = fileService.getPathPrefix() + userName + "/" + "excelFile/" + toDay[0] + "/"
                    + toDay[1] + "/" + toDay[2] + "/" + ftpFileName.toString();
                // 文件上传ftp
                fileService.uploadFile(ftpFilePath, excelFile.toString());

                // 设置成功消息内容
                msg.put("title", super.getSuccTitle(title));
                msg.put("content", super.getSuccContent(createDate));
                msg.put("url", super.getUrl(id));
                msg.put("useraccount", userName);

                // 记录导出完成状态
                exportLogService.updateSucc(id, ftpFilePath, dbName);

            } catch (Exception e) {
                String errmsg = ExceptionUtil.getExceptionDeteil(e, 4000);
                // 设置失败消息内容
                msg.put("title", super.getFailTitle(title));
                msg.put("content", super.getFailContent(createDate, errmsg));
                msg.put("url", "");
                msg.put("useraccount", userName);

                log.error("", e);
                // 记录导出出错状态
                exportLogService.updateFail(id, errmsg, dbName);
            } finally {
                // 发送导出消息到mq
                String responseResult = JsonResponseUtils.responseResult(msg);
                sender.sendToMsg(responseResult);

                // 申请成功后像websocket发送申请信息
                feginWebsocket.setMessageToWebsocket(userName);
            }
        }
    }

    /**
     * 递归导出数据到excel文件，防止jvm oom
     *
     * @param pramsMap
     *            查询数据参数集合
     * @param curr
     *            当前第几页
     * @param excelFile
     *            导出的文件
     * @throws Exception
     *
     */

    private boolean cicleExport(Map<String, Object> pramsMap, int curr, String excelFile, JSONObject jsonObject)
        throws Exception {
        // 查询指定页数的数据
        JSONObject pageData = rzFpxxService.selectByPramsMap(pramsMap, curr, default_size);
        boolean hasNext = pageData.getBooleanValue("hasNext");
        List<FpRzRespVO> dataList = (List<FpRzRespVO>)pageData.get("datalist");
        boolean firstPage = false;
        if (curr == default_curr) {
            firstPage = true;
        }

        // 数据不是最后一页
        if (hasNext) {
            int nextPage = pageData.getIntValue("nextPage");
            // 写入当前页数据
            ExcelPoiUtil.exportListArrayToExcel1(excelFile, title, jsonObject, dataList, firstPage, false);
            // 更新页数
            return cicleExport(pramsMap, nextPage, excelFile, jsonObject);
        } else {
            // 写入最后一页数据
            ExcelPoiUtil.exportListArrayToExcel1(excelFile, title, jsonObject, dataList, firstPage, true);
            return hasNext;
        }

    }
}
