package com.dxhy.core.thread;

import java.util.*;

import javax.annotation.Resource;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.dxhy.common.constant.DbConstant;
import com.dxhy.common.constant.DictConstant;
import com.dxhy.common.datasource.config.DynamicContextHolder;
import com.dxhy.common.enums.JxszcZtEnum;
import com.dxhy.common.service.DictdetaServcice;
import com.dxhy.common.service.impl.TabulateRedisServiceImpl;
import com.dxhy.common.util.ExcelPoiUtil;
import com.dxhy.common.util.ExceptionUtil;
import com.dxhy.common.util.MathUtil;
import com.dxhy.common.util.StringHelper;
import com.dxhy.common.utils.DateUtils;
import com.dxhy.core.dao.TDxOutReasonDao;
import com.dxhy.core.entity.TDxExcelExportlog;
import com.dxhy.core.entity.TDxOutReason;
import com.dxhy.core.feign.IFeginWebsocket;
import com.dxhy.core.model.InvoiceOutVO;
import com.dxhy.core.model.ReceiptInvoiceView;
import com.dxhy.core.rabbitmq.Sender;
import com.dxhy.core.service.export.IExportInvoiceOutService;
import com.dxhy.core.service.singletable.IExcelExportlogService;
import com.dxhy.core.util.InvoiceTypeUtils;
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
 */

@SuppressWarnings("AlibabaMethodTooLong")
@Slf4j

public class InvoiceOutExportThread extends BaseThread {

    @Resource
    private DictdetaServcice dictdetaServcice;

    /**
     * 默认要导出第几页的数据
     */
    private final int default_curr = 1;
    /**
     * 默认每页导出多少条数据
     */
    private final int default_size = 5000;

    /**
     * 文件名前缀
     */
    private final String fileNamePrefix = "outIncomeTax";
    /**
     * 文件名后缀
     */
    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 IExportInvoiceOutService invoiceOutService;

    private final TDxOutReasonDao tDxOutReasonDao;

    private final FileService fileService;

    private final Sender sender;
    private final TabulateRedisServiceImpl tabulateRedisService;

    public InvoiceOutExportThread(IExcelExportlogService exportLogService, List<TDxExcelExportlog> exportLogs,
        IExportInvoiceOutService invoiceOutService, TDxOutReasonDao tDxOutReasonDao, FileService fileService,
        Sender sender, IFeginWebsocket feginWebsocket, TabulateRedisServiceImpl tabulateRedisService, DictdetaServcice dictdetaServcice) {
        this.exportLogService = exportLogService;
        this.exportLogs = exportLogs;
        this.invoiceOutService = invoiceOutService;
        this.fileService = fileService;
        this.tDxOutReasonDao = tDxOutReasonDao;
        this.sender = sender;
        this.feginWebsocket = feginWebsocket;
        this.tabulateRedisService = tabulateRedisService;
        this.dictdetaServcice=dictdetaServcice;
    }

    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 xfName = prams.getString("sellerName");
                String invoiceNo = prams.getString("invoiceNo");
                String reasonId = prams.getString("reasonId");
                String invoiceStatus = prams.getString("invoiceStatus");
                String outStartDate = prams.getString("outStartDate");
                String outEndDate = prams.getString("outEndDate");
                String businessCode = prams.getString("businessCode");
                String company = prams.getString("company");
                String menuId = prams.getString("menuId");
                JSONObject jsonObject = tabulateRedisService.getTabulateExcel(company, menuId);
                // 参数转换为需要的形式
                Map<String, Object> filter = new HashMap<>(16);
                // 转出状态为已转出的发票(全部转出and部分转出)
                List<String> statusList = new ArrayList<>();
                statusList.add(JxszcZtEnum.QBZC.getZcztDm());
                statusList.add(JxszcZtEnum.BFZC.getZcztDm());

                filter.put("invoiceOutStatus", statusList);
                filter.put("orderByClause", "out_date desc");

                // 购方税号
                List<String> allTaxNo = new ArrayList<>();
                if (!StringHelper.isBlank(gfsh)) {
                    allTaxNo = StringHelper.stringToList(gfsh);
                } else {
                    allTaxNo.add(gfsh);
                }
                filter.put("gfshList", allTaxNo);

                // 销方名称
                filter.put("sellerName", StringHelper.isBlank(xfName) ? null : xfName);
                // 发票号码
                filter.put("invoiceNo", StringHelper.isBlank(invoiceNo) ? null : invoiceNo);
                // 转出原因
                if (!StringHelper.isBlank(reasonId) && !"99".equals(reasonId)) {
                    filter.put("reasonId", reasonId);
                }
                // 发票状态
                if (!StringHelper.isBlank(invoiceStatus) && !"99".equals(invoiceStatus)) {
                    filter.put("invoiceStatus", invoiceStatus);
                }
                // 转出开始时间
                filter.put("outStartDate", StringHelper.isBlank(outStartDate) ? null : outStartDate);
                // 转出结束时间
                filter.put("outEndDate", StringHelper.isBlank(outEndDate) ? null : outEndDate);
                // 业务参数
                if (!StringHelper.isBlank(businessCode) && !"99".equals(businessCode)) {
                    filter.put("businessCode", businessCode);
                }
                filter.put("company", company);
                // 导出文件名
                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
                DynamicContextHolder.push(dbName + DbConstant.BUSINESS_READ);
                log.debug("导出文件路径--" + excelFile.toString());
                this.cicleExport(filter, default_curr, excelFile.toString(), exportLog, 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);
            }
        }
    }

    /**
     * @param filter
     * @param defaultCurr
     * @param excelFile
     * @param exportLog
     */
    private void cicleExport(Map<String, Object> filter, int defaultCurr, String excelFile, TDxExcelExportlog exportLog,
        JSONObject jsonObject) throws Exception {
        filter.put("curr", defaultCurr);
        filter.put("size", default_size);
        PageInfo<ReceiptInvoiceView> pageList = invoiceOutService.listExportByInvoice(filter);
        List<InvoiceOutVO> dataList = convertToData(pageList.getList());

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

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

    /**
     * 查询出的数据转为导出data
     *
     * @param list
     * @return
     */
    private List<InvoiceOutVO> convertToData(List<ReceiptInvoiceView> list) {
        List<InvoiceOutVO> dataList = new ArrayList<>();
        int a = 1;
        for (ReceiptInvoiceView view : list) {
            InvoiceOutVO vo = new InvoiceOutVO();
            vo.setXh(String.valueOf(a++));
            // 转出日期
            vo.setOutDate(DateUtils.dateToStr(view.getOutDate()));
            // 发票号码
            vo.setInvoiceCode(view.getInvoiceCode());
            // 发票代码
            vo.setInvoiceNo(view.getInvoiceNo());
            // 发票类型
            vo.setInvoiceType(new InvoiceTypeUtils().invoiceTypeName(view.getInvoiceType()));
            // 开票日期
            vo.setInvoiceDate(DateUtils.dateToStr(view.getInvoiceDate()));
            // 发票状态
            vo.setInvoiceStatusName(
                dictdetaServcice.queryDictName(DictConstant.INVOICE_STATUS, view.getInvoiceStatus()));
            // 购方税号
            vo.setGfsh(view.getGfTaxNo());
            // 购方名称
            vo.setBuyerName(view.getGfName());
            // 销方名称
            vo.setSellerName(view.getXfName());
            // 金额
            vo.setAmount(MathUtil.round(view.getInvoiceAmount().toPlainString()));
            // 税额
            vo.setTaxAmount(MathUtil.round(view.getTaxAmount().toPlainString()));
            // 转出金额
            vo.setOutAmount(MathUtil.round(view.getOutInvoiceAmout().toPlainString()));
            // 转出税额
            vo.setOutTaxAmount(MathUtil.round(view.getOutTaxAmount().toPlainString()));
            vo.setOutTax(MathUtil.round(view.getOutTaxAmount().toPlainString()));
            vo.setOutBelongDate(view.getOutBelongDate());
            // 转出原因
            QueryWrapper<TDxOutReason> query = new QueryWrapper<>();
            query.eq("reason_code", view.getOutReason());
            TDxOutReason reason = tDxOutReasonDao.selectOne(query);
            vo.setReason(reason.getOutReason());
            // 转出备注
            vo.setRemark(view.getOutRemark());

            // 数组构建完毕放入list中
            dataList.add(vo);
        }
        return dataList;
    }
}
