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.common.service.impl.TabulateRedisServiceImpl;
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.JxsebbRespVO;
import com.dxhy.common.rabbitmq.RabbitMqSender;
import com.dxhy.core.service.export.JxsebbcxService;
import com.dxhy.core.util.JsonResponseUtils;
import com.dxhy.oss.service.FileService;
import com.google.common.io.Closer;
import com.google.common.io.Resources;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.*;

/**
 * 进项税额报表查询导出
 *
 * @author user
 */

@Slf4j
@SuppressWarnings({"AlibabaUndefineMagicConstant", "AlibabaMethodTooLong"})
public class JxsebbExportThread extends BaseThread {

    /**
     * 默认要导出第几页的数据
     */
    private final int default_curr = 1;

    /**
     * 文件名前缀
     */
    private final String fileNamePrefix = "bbfpzhcxList";
    /**
     * 文件名后缀
     */
    private final String fileNameSurfix = ".xlsx";
    /**
     * 文件名中间分隔符
     */
    private final String fileSplit = "_";
    /**
     * excel的标题
     */
    private final String title = "进项税额报表";

    private final IExcelExportlogService exportLogService;

    private final List<TDxExcelExportlog> exportLogs;

    private final JxsebbcxService jxsebbcxService;

    private final FileService fileService;

    private final RabbitMqSender sender;
    private final TabulateRedisServiceImpl tabulateRedisService;

    public JxsebbExportThread(IExcelExportlogService exportLogService, List<TDxExcelExportlog> exportLogs,
        JxsebbcxService jxsebbcxService, FileService fileService, RabbitMqSender sender, IFeginWebsocket feginWebsocket,
        TabulateRedisServiceImpl tabulateRedisService) {
        this.exportLogService = exportLogService;
        this.exportLogs = exportLogs;
        this.jxsebbcxService = jxsebbcxService;
        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 skssq = prams.getString("skssq");
                String gfmc = prams.getString("gfmc");
                String company = prams.getString("company");
                // 参数转换为需要的形式
                Map<String, Object> pramsMap = new HashMap<>(16);
                pramsMap.put("dbName", dbName);
                List<String> gfshList = new ArrayList<>();
                if (!StringHelper.isBlank(gfsh)) {
                    gfshList = StringHelper.stringToList(gfsh);
                    pramsMap.put("gfsh", gfshList);
                } else {
                    pramsMap.put("gfsh", gfsh);
                }
                pramsMap.put("skssq", skssq);
                pramsMap.put("gfmc", gfmc);
                pramsMap.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
                this.cicleExport(pramsMap, default_curr, excelFile.toString());

                // 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
     *
     * @param pramsMap
     * @param curr
     * @param excelFile
     * @throws Exception
     */
    private void cicleExport(Map<String, Object> pramsMap, int curr, String excelFile) throws Exception {
        // 查询数据
        JSONObject pageData = jxsebbcxService.selectByPramsMap(pramsMap);
        JxsebbRespVO jxsebbRespVO = (JxsebbRespVO)pageData.get("datalist");
        exportListArrayToExcel(excelFile, title, jxsebbRespVO, pageData);
    }

    public static void exportListArrayToExcel(String excelFile, String title, JxsebbRespVO jxsebbRespVO,
        JSONObject pageData) throws Exception {
        // 文件存储路径是否存在
        File filePath = new File(getFilePath(excelFile));
        if (!filePath.exists()) {
            filePath.mkdirs();
        }

        File file = new File(excelFile);
        // excel不存在则创建
        if (!file.exists()) {
            file.createNewFile();
        }
        final Closer closer = Closer.create();

        final InputStream fs =
            closer.register(Resources.asByteSource(Resources.getResource("template/inputTaxReport.xlsx")).openStream());
        // 创建工作簿
        final XSSFWorkbook workBook = new XSSFWorkbook(OPCPackage.open(fs));

        XSSFSheet sheet = workBook.getSheet("sheet");
        sheet.getRow(2).getCell(3).setCellValue(pageData.getString("skssq"));
        sheet.getRow(2).getCell(1).setCellValue(jxsebbRespVO.getGfmc());
        sheet.getRow(5).getCell(2).setCellValue(jxsebbRespVO.getTotalCount());
        sheet.getRow(5).getCell(3).setCellValue(jxsebbRespVO.getTotalAmount());
        sheet.getRow(5).getCell(5).setCellValue(jxsebbRespVO.getTotalTax());
        sheet.getRow(6).getCell(2).setCellValue(jxsebbRespVO.getTotalCount());
        sheet.getRow(6).getCell(3).setCellValue(jxsebbRespVO.getTotalAmount());
        sheet.getRow(6).getCell(5).setCellValue(jxsebbRespVO.getTotalTax());
        sheet.getRow(8).getCell(2).setCellValue(jxsebbRespVO.getCustomsCount());
        sheet.getRow(8).getCell(5).setCellValue(jxsebbRespVO.getCustomsTax());
        sheet.getRow(9).getCell(2).setCellValue(jxsebbRespVO.getCustomsCount());
        sheet.getRow(9).getCell(5).setCellValue(jxsebbRespVO.getCustomsTax());
        int count = Integer.parseInt(jxsebbRespVO.getTotalCount()) + Integer.parseInt(jxsebbRespVO.getCustomsCount());
        sheet.getRow(20).getCell(2).setCellValue(Integer.toString(count));
        sheet.getRow(20).getCell(3).setCellValue(jxsebbRespVO.getTotalAmount());
        double tax = Double.parseDouble(jxsebbRespVO.getTotalTax()) + Double.parseDouble(jxsebbRespVO.getCustomsTax());
        sheet.getRow(20).getCell(5).setCellValue(Double.toString(tax));
        if (jxsebbRespVO.getTotalOutTax() != null) {
            sheet.getRow(23).getCell(2).setCellValue(jxsebbRespVO.getTotalOutTax());
        }
        if (jxsebbRespVO.getOutTax1() != null) {
            sheet.getRow(24).getCell(2).setCellValue(jxsebbRespVO.getOutTax1());
        }
        if (jxsebbRespVO.getOutTax2() != null) {
            sheet.getRow(25).getCell(2).setCellValue(jxsebbRespVO.getOutTax2());
        }
        if (jxsebbRespVO.getOutTax3() != null) {
            sheet.getRow(26).getCell(2).setCellValue(jxsebbRespVO.getOutTax3());
        }
        if (jxsebbRespVO.getOutTax4() != null) {
            sheet.getRow(27).getCell(2).setCellValue(jxsebbRespVO.getOutTax4());
        }
        if (jxsebbRespVO.getOutTax5() != null) {
            sheet.getRow(28).getCell(2).setCellValue(jxsebbRespVO.getOutTax5());
        }
        if (jxsebbRespVO.getOutTax6() != null) {
            sheet.getRow(29).getCell(2).setCellValue(jxsebbRespVO.getOutTax6());
        }
        if (jxsebbRespVO.getOutTax7() != null) {
            sheet.getRow(30).getCell(2).setCellValue(jxsebbRespVO.getOutTax7());
        }
        if (jxsebbRespVO.getOutTax8() != null) {
            sheet.getRow(31).getCell(2).setCellValue(jxsebbRespVO.getOutTax8());
        }
        if (jxsebbRespVO.getOutTax9() != null) {
            sheet.getRow(32).getCell(2).setCellValue(jxsebbRespVO.getOutTax9());
        }
        if (jxsebbRespVO.getOutTax0() != null) {
            sheet.getRow(33).getCell(2).setCellValue(jxsebbRespVO.getOutTax0());
        }

        sheet.getRow(36).getCell(2).setCellValue(jxsebbRespVO.getTotalCount());
        sheet.getRow(36).getCell(3).setCellValue(jxsebbRespVO.getTotalAmount());
        sheet.getRow(36).getCell(5).setCellValue(jxsebbRespVO.getTotalTax());
        sheet.getRow(41).getCell(2).setCellValue(jxsebbRespVO.getCustomsCount());
        sheet.getRow(41).getCell(5).setCellValue(jxsebbRespVO.getCustomsTax());
        sheet.getRow(42).getCell(2).setCellValue(jxsebbRespVO.getCustomsCount());
        sheet.getRow(42).getCell(5).setCellValue(jxsebbRespVO.getCustomsTax());
        sheet.getRow(49).getCell(2).setCellValue(jxsebbRespVO.getTotalCount());
        sheet.getRow(49).getCell(3).setCellValue(jxsebbRespVO.getTotalAmount());
        sheet.getRow(49).getCell(5).setCellValue(jxsebbRespVO.getTotalTax());

        FileOutputStream outStream = new FileOutputStream(file);
        workBook.write(outStream);
        outStream.flush();
        outStream.close();
        workBook.close();
        closer.close();
    }

    /**
     * 根据全路径获取存储路径
     *
     * @param fileName
     * @return
     *
     */
    private static String getFilePath(String fileName) {
        StringBuilder filePath = new StringBuilder();
        // linux服务器
        if (!fileName.contains(":")) {
            filePath.append("/");
        }
        String[] filePaths = fileName.split("/");

        for (int i = 0; i < filePaths.length - 1; i++) {
            if (!StringHelper.isBlank(filePaths[i])) {
                filePath.append(filePaths[i]);
                filePath.append("/");
            }
        }
        return filePath.toString();
    }
}
