package com.dxhy.core.thread;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.FplxEnum;
import com.dxhy.common.service.impl.TabulateRedisServiceImpl;
import com.dxhy.common.util.*;
import com.dxhy.common.utils.DateUtils;
import com.dxhy.core.entity.TDxExcelExportlog;
import com.dxhy.core.feign.IFeginWebsocket;
import com.dxhy.core.model.CautionExpirationReqVO;
import com.dxhy.core.model.RecordInvoiceModel;
import com.dxhy.core.rabbitmq.Sender;
import com.dxhy.core.service.export.IExportCautionService;
import com.dxhy.core.service.singletable.IExcelExportlogService;
import com.dxhy.core.util.JsonResponseUtils;
import com.dxhy.oss.service.FileService;
import com.github.pagehelper.PageInfo;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * @author user
 */

@Slf4j

public class CautionExportExpirationThread extends BaseThread {

    /**
     * 默认要导出第几页的数据
     */
    private final int default_curr = 1;
    /**
     * 默认每页导出多少条数据
     */
    private final int default_size = 5000;
    /**
     * 文件名前缀
     */
    private final String fileNamePrefix = "cautionExpiration";
    /**
     * 文件名后缀
     */
    private final String fileNameSurfix = ".xls";
    /**
     * 文件名中间分隔符
     */
    private final String fileSplit = "_";
    /**
     * excel的标题
     */
    private final String title = "逾期预警";
    /**
     * 导出excel的列名
     */
    private final String[] titleColumns =
        {"序号", "认证截止月", "发票类型", "发票代码", "发票号码", "开票日期", "购方名称", "销方名称", "金额", "税额", "抵扣税额"};

    private final List<TDxExcelExportlog> exportLogs;

    private final IExcelExportlogService exportLogService;

    private final IExportCautionService cautionService;

    private final FileService fileService;

    private final Sender sender;
    private final TabulateRedisServiceImpl tabulateRedisService;

    public CautionExportExpirationThread(IExcelExportlogService exportLogService, List<TDxExcelExportlog> exportLogs,
        IExportCautionService cautionService, FileService fileService, Sender sender, IFeginWebsocket feginWebsocket,
        TabulateRedisServiceImpl tabulateRedisService) {
        this.exportLogService = exportLogService;
        this.exportLogs = exportLogs;
        this.cautionService = cautionService;
        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 params = JSONObject.parseObject(condition);

                // 逾期预警
                CautionExpirationReqVO reqVO =
                    JSONObject.parseObject(params.toJSONString(), CautionExpirationReqVO.class);

                // 导出文件名
                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，切换到read数据库
                DynamicContextHolder.push(dbName + DbConstant.BUSINESS_READ);
                this.cicleExport(reqVO, default_curr, excelFile.toString(), exportLog);

                // 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);
            }
        }
    }

    /**
     * 逾期预警递归导出
     *
     * @param reqVO
     * @param defaultCurr
     * @param excelFile
     * @param exportLog
     * @throws Exception
     */
    private void cicleExport(CautionExpirationReqVO reqVO, int defaultCurr, String excelFile,
        TDxExcelExportlog exportLog) throws Exception {

        List<String> allTaxNo = new ArrayList<>();
        if (!StringHelper.isBlank(reqVO.getGfsh())) {
            allTaxNo = StringHelper.stringToList(reqVO.getGfsh());
        }
        reqVO.setAllTaxNo(allTaxNo);
        Page<RecordInvoiceModel> page = new Page<>(defaultCurr, default_size);
        PageInfo<RecordInvoiceModel> pageList = cautionService.listExpiration(page, reqVO, allTaxNo);
        List<String[]> dataList = convertToExpirationData(pageList.getList());

        boolean firstPage = false;
        if (pageList.isIsFirstPage()) {
            firstPage = true;
        }

        // 已经是最后一页
        if (!pageList.isIsLastPage()) {
            // 写入数据
            ExcelPoiUtil.exportListArrayToExcel(excelFile, title, titleColumns, dataList, firstPage, false);
        } else if (pageList.isIsLastPage()) {
            ExcelPoiUtil.exportListArrayToExcel(excelFile, title, titleColumns, dataList, firstPage, true);
            return;
        }
        // 更新页数
        defaultCurr++;
        cicleExport(reqVO, defaultCurr, excelFile, exportLog);
    }

    /**
     * 逾期预警view
     *
     * @param list
     * @return
     */
    private List<String[]> convertToExpirationData(List<RecordInvoiceModel> list) {
        List<String[]> dataList = new ArrayList<>();
        int xh = 0;
        String zjje = "0";
        String zjse = "0";
        String dkse = "0";
        for (RecordInvoiceModel record : list) {
            String[] ary = new String[11];
            xh = xh + 1;
            ary[0] = String.valueOf(xh);
            // 认证截止日
            ary[1] = record.getCutApproveDate();
            // 发票类型
            if ("01".equals(record.getInvoiceType()) || "1".equals(record.getInvoiceType())) {
                ary[2] = FplxEnum.ZP.getFplxMc(FplxEnum.ZP.getIndex());
            } else if ("03".equals(record.getInvoiceType()) || "3".equals(record.getInvoiceType())) {
                ary[2] = FplxEnum.JDC.getFplxMc(FplxEnum.JDC.getIndex());
            } else {
                ary[2] = FplxEnum.TXF.getFplxMc(FplxEnum.TXF.getIndex());
            }
            // 发票代码
            ary[3] = record.getInvoiceCode();
            // 发票号码
            ary[4] = record.getInvoiceNo();
            // 开票日期
            ary[5] = record.getInvoiceDate();
            // 购方名称
            ary[6] = record.getGfName();
            // 销方名称
            ary[7] = record.getXfName();
            // 未税金额 = 金额
            ary[8] = MathUtil.round(record.getInvoiceAmount());
            // 税额
            ary[9] = MathUtil.round(record.getTaxAmount());
            // 抵扣税额
            if ("".equals(record.getDkAmount()) || record.getDkAmount() == null) {
                ary[10] = MathUtil.round(record.getTaxAmount());
            } else {
                ary[10] = MathUtil.round(record.getDkAmount());
            }
            zjje = MathUtil.add(zjje, record.getInvoiceAmount());
            zjse = MathUtil.add(zjse, record.getTaxAmount());
            if ("".equals(record.getDkAmount()) || record.getDkAmount() == null) {
                dkse = MathUtil.add(dkse, record.getTaxAmount());
            } else {
                dkse = MathUtil.add(dkse, record.getDkAmount());
            }
            dataList.add(ary);
        }
        String zjsl = String.valueOf(list.size());
        String[] hjxx = new String[13];
        hjxx[1] = "合计";
        hjxx[2] = zjsl;
        hjxx[8] = AmountFormatUtil.fmtMicrometer(zjje);
        hjxx[9] = AmountFormatUtil.fmtMicrometer(zjse);
        hjxx[10] = AmountFormatUtil.fmtMicrometer(dkse);
        dataList.add(hjxx);
        return dataList;
    }
}
