package com.zbkj.service.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.huifu.bspay.sdk.opps.core.utils.RsaUtils;
import com.zbkj.common.constants.Constants;
import com.zbkj.common.dto.*;
import com.zbkj.common.excel.ExcelUtil;
import com.zbkj.common.exception.CrmebWalletException;
import com.zbkj.common.model.huifu.*;
import com.zbkj.common.utils.DateUtils;
import com.zbkj.common.utils.RedisUtil;
import com.zbkj.service.config.PaymentChannel;
import com.zbkj.service.dao.*;
import com.zbkj.service.huifu.constants.*;
import com.zbkj.service.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <b>  </b>
 * @author ZXF
 * @create 2023/07/31 0031 11:30
 * @version
 * @注意事项 </b>
 */
@Service
public class CommonWalletServiceImpl extends ServiceImpl<HuifuWalletDao, HuifuWallet> implements CommonWalletService {

    private static final Logger logger = LoggerFactory.getLogger(CommonWalletService.class);

    @Resource
    private HuifuWalletAccountDetailDao huifuWalletAccountDetailDao;

    @Resource
    private HuifuWalletTradeDao huifuWalletTradeDao;

    @Resource
    private HuifuWalletAccountDao huifuWalletAccountDao;
    @Resource
    private BankConfigDao bankConfigDao;

    @Resource
    private HuifuWalletTranslogDao huifuWalletTranslogDao;
    @Resource
    private HuifuWalletReconciliationDao huifuWalletReconciliationDao;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private TransactionTemplate transactionTemplate;
    @Autowired
    HuifuReconcileService huifuReconcileService;
    @Autowired
    TransactionLogService transactionLogService;
    @Autowired
    private RedissonClient redisson;

    private final static String TRANSFERKEY = "Callback:";

    private static final int expireTime = 10 * 60;


    /**
     * 银行信息查询
     * @param bankConfig
     * @return
     */
    @Override
    public List<BankConfig> findBank(BankConfig bankConfig) throws CrmebWalletException {
        List<BankConfig> list = null;
        if (StringUtil.isEmpty(bankConfig.getBankCode())
                &&bankConfig.getBranchCode() == null
                &&StringUtil.isEmpty(bankConfig.getBankName())
                &&StringUtil.isEmpty(bankConfig.getBranchName())) {
            String key = "BANKS-HEAD";
            if(redisUtil.exists(key)) {
                return redisUtil.get(key);
            }
            list = bankConfigDao.findBankHead();
            redisUtil.set(key, list, (long) expireTime, TimeUnit.MINUTES);
        }else{
            list = bankConfigDao.findBank(bankConfig);
            if(list.size()>100){
                throw new CrmebWalletException("支行名称关键字不够精确");
            }
        }
        return list;
    }

    /**
     * <b> 返回常量包装 </b>
     * @param type 1获取code 2获取desc
     * @author ZXF
     * @create 2023/09/12 0012 11:22
     * @version
     * @注意事项 </b>
     */
    public static String RET(Map<String, Object> response,int type){
        if(type == 1){
            return response.get("resp_code").toString();
        }
        return response.get("resp_desc").toString();
    }

    /**
     * <b> 获取企业钱包账户交易明细（请求转存数据，当天只能查到昨天的数据） </b>
     * @author ZXF
     * @create 2023/04/23 0023 10:37
     * @version
     * @注意事项 </b>
     */
    @Override
    public PageInfo<HuifuWalletAccountDetail> thisHuifuWalletAccountTradeDetail(HuifuWalletAccountDetailDto dto) throws CrmebWalletException {
        if (StringUtils.isEmpty(dto.getUniId())) {
            throw new CrmebWalletException("企业ID不能为空");
        }
        if (dto.getPageNumber() == null) {
            throw new CrmebWalletException("第几页不能为空");
        }
        if (dto.getPageSize() == null) {
            throw new CrmebWalletException("每页多少行不能为空");
        }
        if (StringUtil.isEmpty(dto.getStartDate())) {
            throw new CrmebWalletException("开始日期不能为空");
        }
        if (StringUtil.isEmpty(dto.getEndDate())) {
            throw new CrmebWalletException("结束日期不能为空");
        }
        dto.setStartDate(dto.getStartDate().replace("-",""));
        dto.setEndDate(dto.getEndDate().replace("-",""));
        dto.setIsHideCheck("1");
        PageHelper.startPage(dto.getPageNumber(), dto.getPageSize());
        List<HuifuWalletAccountDetail> detailList = huifuWalletAccountDetailDao.selectByUniIdAndDate(dto);
        return new PageInfo(detailList);
    }

    /**
     * 企业钱包充值回调
     *
     * @param dto
     * @return
     * @author llc
     * @date 2019-06-28
     */
    @Override
    public String huifuWalletRechargeCallback(HuifuRequestDataDto dto) {
        transactionLogService.save("huifuWalletRechargeCallback",Constants.Y, JSON.toJSONString(dto),"ok", PaymentChannel.HUIFU.toString());
        if(!HFConstants.REQUEST_SUCC_CODE.equals(dto.getResp_code())){
            return "";
        }
        // 使用汇付公钥验签
        if (!RsaUtils.verify(dto.getData(), HFProfileConstants.RSA_PUBLIC_KEY, dto.getSign())) {
            logger.info("企业钱包充值回调，异步回调开始，fail=验签失败");
            // 验签失败处理
            return "";
        }
        Map<String, Object> response = JSON.parseObject(dto.getData(), Map.class);
        String status = Constants.tradeStatus(response.get("trans_stat").toString());

        String reqSeqId = response.get("req_seq_id").toString();
        String lockId = TRANSFERKEY+reqSeqId;
        RLock lock = redisson.getLock(lockId);
        try {
            if(lock.tryLock(3,10, TimeUnit.SECONDS)){
                logger.debug(lockId+":getLock: " + Thread.currentThread().getId());
                HuifuWalletTrade huifuWalletTrade = huifuWalletTradeDao.getHuifuWalletTradeByHfSeqId(response.get("hf_seq_id").toString());
                if(status.equals(huifuWalletTrade.getTradeStatus())){
                    return "RECV_ORD_ID_"+huifuWalletTrade.getHfSeqId();
                }
                Boolean execute = transactionTemplate.execute(e -> {
                    huifuWalletTrade.setTransFinishTime(response.get("trans_date")+""+response.get("trans_time"));
                    huifuWalletTrade.setErrorMsg(RET(response,2));
                    huifuWalletTrade.setTradeStatus(status);
                    huifuWalletTrade.setUpdateTime(new Date());
                    /*** 更新企业钱包账户交易记录 ***/
                    huifuWalletTradeDao.updateHuifuWalletTrade(huifuWalletTrade);
                    logger.info("企业钱包充值回调，异步回调开始，succ2={},errorMsg={}", reqSeqId, huifuWalletTrade.getErrorMsg());
                    return Boolean.TRUE;
                });
                if (!execute) {
                    logger.error("企业钱包充值回调，异步回调入库失败，request={}", response.get("resp_data").toString());
                    return "";
                }
                return "RECV_ORD_ID_" + reqSeqId;
            }else{
                return "";
            }
        } catch (InterruptedException e) {
            logger.error("huifuWalletRechargeCallback error", e);
            return "";
        }finally {
            if (lock.isHeldByCurrentThread()) {
                logger.debug(lockId+":unLock: " + Thread.currentThread().getId());
                lock.unlock();
            }
        }
    }

    /**
     * 企业钱包提现回调
     *
     * @param messageBody
     * @return
     * @author llc
     * @date 2019-06-28
     */
    @Override
    public String huifuWalletExtractCallback(String messageBody) {
        Map<String, Object> response = pathToJson(messageBody);
        logger.info("企业钱包提现回调，异步回调开始，参数，response={}", response.toString());
        transactionLogService.save("huifuWalletExtractCallback", Constants.Y, response.toString(), "ok",PaymentChannel.HUIFU.toString());
        if (!HFConstants.REQUEST_SUCC_CODE.equals(response.get("resp_code").toString())) {
            return "ok";
        }
        // 验签请参sign
        String sign = response.get("sign").toString();
        // 使用汇付公钥验签
        if (!RsaUtils.verify(response.get("resp_data").toString(), HFProfileConstants.RSA_PUBLIC_KEY, sign)) {
            logger.info("企业钱包提现回调，异步回调开始，fail=验签失败");
            // 验签失败处理
            return "";
        }
        JSONObject dataObj = JSON.parseObject(response.get("resp_data").toString());
        String reqSeqId = dataObj.getString("req_seq_id");
        String lockId = TRANSFERKEY+reqSeqId;
        RLock lock = redisson.getLock(lockId);
        try {
            if(lock.tryLock(3,10, TimeUnit.SECONDS)){
                logger.debug(lockId+":getLock: " + Thread.currentThread().getId());
                HuifuWalletTrade huifuWalletTrade = huifuWalletTradeDao.getHuifuWalletTradeByHfSeqId(dataObj.get("hf_seq_id").toString());
                // 支付成功记录已存在
                if (Constants.TRADESTATUS_JYCG.equals(huifuWalletTrade.getTradeStatus())) {
                    logger.info("企业钱包提现回调，异步回调开始，succ1={}", reqSeqId);
                    return "RECV_ORD_ID_" + reqSeqId;
                }
                Boolean execute = transactionTemplate.execute(e -> {
                    huifuWalletTrade.setTransFinishTime(dataObj.get("req_date").toString());
                    huifuWalletTrade.setErrorMsg(RET(response,2));
                    huifuWalletTrade.setTradeStatus(Constants.tradeStatus(dataObj.get("trans_stat").toString()));
                    huifuWalletTrade.setUpdateTime(new Date());
                    /*** 更新企业钱包账户交易记录 ***/
                    huifuWalletTradeDao.updateHuifuWalletTrade(huifuWalletTrade);
                    logger.info("企业钱包提现回调，异步回调开始，succ2={},errorMsg={}", reqSeqId, huifuWalletTrade.getErrorMsg());
                    return Boolean.TRUE;
                });
                if (!execute) {
                    logger.error("企业钱包提现回调，异步回调入库失败，request={}", response.get("resp_data").toString());
                    return "";
                }
                return "RECV_ORD_ID_" + reqSeqId;
            }else{
                return "";
            }
        } catch (InterruptedException e) {
            logger.error("huifuWalletExtractCallback error", e);
            return "";
        }finally {
            if (lock.isHeldByCurrentThread()) {
                logger.debug(lockId+":unLock: " + Thread.currentThread().getId());
                lock.unlock();
            }
        }
    }

    private Map<String, Object> pathToJson(String urlData){
        String data = null;
        try {
            data = URLDecoder.decode(urlData, "UTF-8");
        }catch (Exception e){
            logger.error("解码失败：{}", e);
        }
        Map<String, Object> collect = Arrays.stream(data.split("&"))
                .map(str -> str.split("="))
                .collect(Collectors.toMap(x -> x[0], x -> x.length == 2 ? x[1] : "",
                        (u, v) -> {
                            throw new IllegalStateException(String.format("Duplicate key %s", u));
                        }, LinkedHashMap::new));
        return collect;
    }

    /**
     * 企业钱包查询交易流水记录
     *
     * @param huifuWalletTrade
     * @return
     * @author llc
     * @date 2019-06-28
     */
    @Override
    public HuifuWalletTrade getWalletTradeInfo(HuifuWalletTrade huifuWalletTrade) throws CrmebWalletException {
        if (huifuWalletTrade.getId() == null) {
            throw new CrmebWalletException("企业钱包交易流水号不能为空");
        }
        /*** 查询企业钱包交易信息 ***/
        huifuWalletTrade = huifuWalletTradeDao.getHuifuWalletTradeById(huifuWalletTrade.getId());
        return huifuWalletTrade;
    }

    /**
     * <b> 交易结算对账文件重新生成 </b>
     * @param tradeDate 指定日期，例：20230816
     * @author ZXF
     * @create 2023/08/12 0012 13:33
     * @version
     * @注意事项 </b>
     */
    @Override
    public String reconciliationReplay(String tradeDate) {
        //指定日期有做过交易的汇付号进行对账单查询
        huifuReconcileService.reconcileOrder(tradeDate,HFProfileConstants.HUIFU_ID);
        huifuReconcileService.reconcileSettle(tradeDate,HFProfileConstants.HUIFU_ID);
//        huifuReconcileService.reconcileSettleuser(tradeDate,HFProfileConstants.HUIFU_ID);
        huifuReconcileService.reconcileOutcash(tradeDate,HFProfileConstants.HUIFU_ID);
        huifuReconcileService.reconcileSplit(tradeDate,HFProfileConstants.HUIFU_ID);
        huifuReconcileService.reconcileSplitWS(tradeDate);
        return "1";
    }

    /**
     * 企业钱包账户对账数据生成
     *
     * @author llc
     * @date 2019-08-20
     */
    @Override
    public String createHuifuWalletReconciliation() {
//        String days[] = {"20230816"};
//        String days[] = {"20230810","20230811","20230812","20230813","20230814","20230815"};
        String days[] = {DateUtils.formatDate(DateUtils.addDays(new Date(),-2),"yyyyMMdd"),DateUtils.formatDate(DateUtils.addDays(new Date(),-1),"yyyyMMdd"),DateUtils.formatDate(new Date(),"yyyyMMdd")};
        for(String day : days){
            //指定日期有做过交易的汇付号进行对账单查询
            huifuReconcileService.reconcileOrder(day,HFProfileConstants.HUIFU_ID);
            huifuReconcileService.reconcileSettle(day,HFProfileConstants.HUIFU_ID);
            huifuReconcileService.reconcileOutcash(day,HFProfileConstants.HUIFU_ID);
            huifuReconcileService.reconcileSplit(day,HFProfileConstants.HUIFU_ID);
            huifuReconcileService.reconcileSplitWS(day);
        }
        return "1";
    }

    /**
     * 获取企业钱包账户对账数据
     *
     * @author llc
     * @date 2019-09-19
     */
    @Override
    public Map<String, Object> getHuifuWalletReconciliation(HuifuWalletTradeDto dto) throws CrmebWalletException {
        if (dto.getPageNumber() == null) {
            throw new CrmebWalletException("第几页不能为空");
        }
        if (dto.getPageSize() == null) {
            throw new CrmebWalletException("每页多少行不能为空");
        }
        if (StringUtil.isEmpty(dto.getFundFlowType())) {
            throw new CrmebWalletException("资金流向不能为空");
        }
        if (StringUtils.isEmpty(dto.getUniId())) {
            throw new CrmebWalletException("企业ID不能为空");
        }
        if (StringUtil.isNotEmpty(dto.getStartDate())) {
            dto.setStartDate(dto.getStartDate().replace("-",""));
        }
        if (StringUtil.isNotEmpty(dto.getEndDate())) {
            dto.setEndDate(dto.getEndDate().replace("-",""));
        }
        PageHelper.startPage(dto.getPageNumber(), dto.getPageSize());
        /*** 查询企业钱包账户对账数据列表 ***/
        List<Map<String, Object>> list = huifuWalletReconciliationDao.getWalletReconciliationList(dto);

        /*** 获取企业钱包账户对账统计数据 ***/
        Map<String, Object> map = huifuWalletReconciliationDao.getWalletReconciliationSum(dto);

        PageInfo pageInfo = new PageInfo(list);

        if (map != null) {
            map.put("pageInfo", pageInfo); // 分页信息
        }
        return map;

    }

    /**
     * 导出企业钱包账户对账数据
     *
     * @author llc
     * @date 2019-09-20
     */
    @Override
    public String exportHuifuWalletReconciliation(HuifuWalletTradeDto dto, HttpServletResponse response) throws CrmebWalletException {
        if (StringUtil.isEmpty(dto.getFundFlowType())) {
            throw new CrmebWalletException("资金流向不能为空");
        }
        if (StringUtils.isEmpty(dto.getUniId())) {
            throw new CrmebWalletException("企业ID不能为空");
        }
        if (StringUtils.isNotEmpty(dto.getStartDate())) {
            dto.setStartDate(dto.getStartDate().replace("-",""));
        }
        if (StringUtils.isNotEmpty(dto.getEndDate())) {
            dto.setEndDate(dto.getEndDate().replace("-",""));
        }
        OutputStream os = null;
        HSSFWorkbook wb = new HSSFWorkbook();
        try {
            String fileName = "对账数据" + DateUtil.format(new Date(),"yyyyMMddHHmmss") + ".xls";
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + new String(fileName.getBytes("gb2312"), "ISO8859-1"));
            os = response.getOutputStream();
            HSSFSheet sheet1 = wb.createSheet("对账数据");


            /*** 查询企业钱包账户对账数据列表 ***/
            List<Map<String, Object>> list = huifuWalletReconciliationDao.getWalletReconciliationList(dto);

            /*** 填充文本样式 ***/
            CellStyle stringStyle = ExcelUtil.getStringStyle(wb);

            /**** 生成sheet1的内容 ***/
            HSSFFont titleFont = wb.createFont();
            HSSFCellStyle titleStyle = wb.createCellStyle();
            titleFont.setFontHeightInPoints((short) 11);
            titleFont.setColor(HSSFColor.BLUE.index);
            titleFont.setFontName("黑体");
            titleStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中
            titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
            titleStyle.setFont(titleFont);
            titleStyle.setWrapText(true);
            HSSFDataFormat format = wb.createDataFormat();
            titleStyle.setDataFormat(format.getFormat("@"));

            /**** 生成sheet1的内容 ***/
            /*** 获取企业钱包账户对账统计数据 ***/
            Map<String, Object> map = huifuWalletReconciliationDao.getWalletReconciliationSum(dto);
            String headerTitle = "";
            if (map == null) {
                headerTitle = MessageFormat.format("总笔数：【{0}】笔 | 总金额：【{1}】元 | 成功笔数：【{2}】笔 | 成功金额：【{3}】元 | 失败笔数：【{4}】笔 | 失败金额：【{5}】元 | 处理中笔数：【{6}】笔 | 处理中金额：【{7}】元",
                        0, 0, 0, 0, 0, 0, 0, 0);
            } else {
                headerTitle = MessageFormat.format("总笔数：【{0}】笔 | 总金额：【{1}】元 | 成功笔数：【{2}】笔 | 成功金额：【{3}】元 | 失败笔数：【{4}】笔 | 失败金额：【{5}】元 | 处理中笔数：【{6}】笔 | 处理中金额：【{7}】元",
                        String.valueOf(map.get("totalCount")), String.valueOf(map.get("sumAmount")), String.valueOf(map.get("successCount")), String.valueOf(map.get("successAmount")), String.valueOf(map.get("errorCount")), String.valueOf(map.get("errorAmount")), String.valueOf(map.get("processingCount")), String.valueOf(map.get("processingAmount")));
            }
            /*** 填充第一行数据 ***/
            HSSFCellStyle titleStyle1 = wb.createCellStyle();
            HSSFFont titleFont1 = wb.createFont();
            titleFont1.setFontHeightInPoints((short) 11);
            titleFont1.setColor(HSSFColor.RED.index);
            titleFont1.setFontName("黑体");
            titleStyle1.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
            titleStyle1.setFont(titleFont1);
            titleStyle1.setWrapText(true);
            HSSFRow rowFirst = sheet1.createRow(0); // 第一个sheet的第一行为标题
            rowFirst.setHeight((short) (1000));
            sheet1.addMergedRegion(new CellRangeAddress(0, (short) 0, 0, 13));
            HSSFCell titleCell = rowFirst.createCell(0);
            titleCell.setCellValue(headerTitle);
            titleCell.setCellStyle(titleStyle1);

            /*** 填充第二行数据 ***/
            HSSFRow secondFirst = sheet1.createRow(1);
            String[] secondArr = {"序号", "交易流水号", "银行交易类型", "交易状态", "交易订单创建时间", "交易金额", "出账方户名", "出账方账号", "出账方银行", "入账方户名", "入账方账号", "入账方银行", "入账方证件号", "备注", "支付渠道"};
            int column;
            for (int i = 0; i < secondArr.length; i++) {
                HSSFCell cell = secondFirst.createCell(i); // 获取第二行的每个单元格
                if (i == 0) {
                    column = 1500;
                } else if (i == 4) {
                    column = 5000;
                } else if (i == 1 || i == 7 || i == 10 || i == 13) {
                    column = 8000;
                } else if (i == 6 || i == 9) {
                    column = 10000;
                } else if (i == 13) {
                    column = 14000;
                } else {
                    column = 4000;
                }
                sheet1.setColumnWidth(i, column); // 设置每列的列宽
                sheet1.setDefaultColumnStyle(i, stringStyle); // 设置单元格格式 --文本格式
                cell.setCellStyle(titleStyle); // 文本格式
            }

            /*** 填充第二行数据 ***/
            for (int i = 0; i < secondArr.length; i++) {
                HSSFCell cell = secondFirst.createCell(i); // 获取第一行的每个单元格
                cell.setCellValue(secondArr[i]);
                cell.setCellStyle(titleStyle);
            }

            /*** 字体颜色样式 ***/
            CellStyle greenStyle = ExcelUtil.getColorStyle(wb, IndexedColors.SEA_GREEN.index);// 青绿色样式
            CellStyle redStyle = ExcelUtil.getColorStyle(wb, IndexedColors.RED.index); // 红色样式
            CellStyle blueStyle = ExcelUtil.getColorStyle(wb, IndexedColors.BLUE.index); // 红色样式
            HSSFRow row = null;
            int rowIndex = 2;
            for (Map<String, Object> result : list) {
                row = sheet1.createRow(rowIndex);
                HSSFCell cell0 = row.createCell(0);
                cell0.setCellValue(rowIndex - 1);
                HSSFCell cell1 = row.createCell(1);
                cell1.setCellValue(result.get("tradeSerialNo") != null ? result.get("tradeSerialNo").toString() : null); // 交易流水号
                HSSFCell cell2 = row.createCell(2);
                cell2.setCellValue(result.get("bankTradeType") != null ? result.get("bankTradeType").toString() : null); // 银行交易类型
                HSSFCell cell3 = row.createCell(3);
                cell3.setCellValue(result.get("tradeStatus") != null ? result.get("tradeStatus").toString() : null); // 交易状态
                if (ObjectUtil.equal(result.get("tradeStatus"), "交易成功")) {
                    cell3.setCellStyle(greenStyle);
                } else if (ObjectUtil.equal(result.get("tradeStatus"), "交易失败")) {
                    cell3.setCellStyle(redStyle);
                } else {
                    cell3.setCellStyle(blueStyle);
                }
                HSSFCell cell4 = row.createCell(4);
                cell4.setCellValue(result.get("tradeStartTime") != null ? result.get("tradeStartTime").toString() : null); // 交易订单创建时间
                HSSFCell cell5 = row.createCell(5);
                cell5.setCellValue(result.get("tradeAmount") != null ? result.get("tradeAmount").toString() : null); // 交易金额
                cell5.setCellStyle(redStyle);
                HSSFCell cell6 = row.createCell(6);
                cell6.setCellValue(result.get("expendAccountName") != null ? result.get("expendAccountName").toString() : null);// 出账方户名
                HSSFCell cell7 = row.createCell(7);
                cell7.setCellValue(result.get("expendAccountNo") != null ? result.get("expendAccountNo").toString() : null);// 出账方账号
                HSSFCell cell8 = row.createCell(8);
                cell8.setCellValue(result.get("expendBank") != null ? result.get("expendBank").toString() : null);// 出账方银行
                HSSFCell cell9 = row.createCell(9);
                cell9.setCellValue(result.get("incomeAccountName") != null ? result.get("incomeAccountName").toString() : null);// 入账方户名
                HSSFCell cell10 = row.createCell(10);
                cell10.setCellValue(result.get("incomeAccountNo") != null ? result.get("incomeAccountNo").toString() : null);// 入账方账号
                HSSFCell cell11 = row.createCell(11);
                cell11.setCellValue(result.get("incomeBank") != null ? result.get("incomeBank").toString() : null);// 入账方银行
                HSSFCell cell12 = row.createCell(12);
                cell12.setCellValue(result.get("incomeCerNo") != null ? result.get("incomeCerNo").toString() : null);// 入账方证件号
                HSSFCell cell13 = row.createCell(13);
                cell13.setCellValue(result.get("remark") != null ? result.get("remark").toString() : null);// 备注
                HSSFCell cell14 = row.createCell(14);
                cell14.setCellValue(result.get("payChannel") != null ? result.get("payChannel").toString() : null);// 支付渠道
                rowIndex++;
            }
            wb.write(os);
            os.close();
            wb.close();
        } catch (Exception e) {
            throw new CrmebWalletException(e.getMessage());
        } finally {
            try {
                os.close();
                wb.close();
            } catch (IOException e1) {
            }
        }
        return "0";
    }

    /**
     * <b> 根据业务编码或业务交易流水号查询交易信息 </b>
     * @author ZXF
     * @create 2023/03/23 0023 10:20
     * @version
     * @注意事项 </b>
     */
    @Override
    public List<HuifuWalletTrade> getHuifuWalletTradeBySeqAndCode(HuifuWalletTrade huifuWalletTrade) throws CrmebWalletException {
        if (huifuWalletTrade.getBusinessCode() == null) {
            throw new CrmebWalletException("业务编码不能为空");
        }
        /*** 查询企业钱包交易信息 ***/
        List<HuifuWalletTrade> list = huifuWalletTradeDao.getHuifuWalletTradeBySeqAndCode(huifuWalletTrade);
        return list;
    }

    /**
     * <b> 余额支付交易分账明细查询 定时任务 TODO 实时依据余额支付接口生成收支明细 </b>
     * @author ZXF
     * @create 2023/11/13 0013 23:31
     * @version
     * @注意事项 </b>
     */
    /*@Override
    public void payTradeDetailTaskSch() {
//        查询所有未生成明细的单子
        List<Map<String, String>> list = huifuWalletTradeDao.findHuifuWalletTradeByDay();
        for (Map<String, String> map:list) {
            huifuReconcileService.payTradeDetailTask(map.get("accountNo"),map.get("hfSeqId"),map.get("tradeDate"));
        }
    }*/


    /**
     * 导出企业钱包账户交易明细数据
     *
     * @author llc
     * @date 2019-09-20
     */
    @Override
    public String exportHuifuWalletAccountTradeDetail(HuifuWalletAccountDetailDto dto, HttpServletResponse response) throws CrmebWalletException {
        if (StringUtils.isEmpty(dto.getUniId())) {
            throw new CrmebWalletException("企业ID不能为空");
        }
        if (StringUtil.isEmpty(dto.getStartDate())) {
            throw new CrmebWalletException("开始日期不能为空");
        }
        if (StringUtil.isEmpty(dto.getEndDate())) {
            throw new CrmebWalletException("结束日期不能为空");
        }
        OutputStream os = null;
        HSSFWorkbook wb = new HSSFWorkbook();
        try {
            String fileName = "收支明细" + DateUtil.format(new Date(),"yyyyMMddHHmmss") + ".xls";
            response.setContentType("application/vnd.ms-excel");
            response.setHeader("Content-Disposition",
                    "attachment;fileName=" + new String(fileName.getBytes("gb2312"), "ISO8859-1"));
            os = response.getOutputStream();
            HSSFSheet sheet1 = wb.createSheet("收支明细");


            /*** 查询企业钱包账户交易明细数据列表 ***/
            dto.setStartDate(dto.getStartDate().replace("-",""));
            dto.setEndDate(dto.getEndDate().replace("-",""));
            dto.setIsHideCheck("1");
            List<HuifuWalletAccountDetail> detailList = huifuWalletAccountDetailDao.selectByUniIdAndDate(dto);

            /*** 填充文本样式 ***/
            CellStyle stringStyle = ExcelUtil.getStringStyle(wb);

            /**** 生成sheet1的内容 ***/
            HSSFFont titleFont = wb.createFont();
            HSSFCellStyle titleStyle = wb.createCellStyle();
            titleFont.setFontHeightInPoints((short) 11);
            titleFont.setColor(HSSFColor.BLUE.index);
            titleFont.setFontName("黑体");
            titleStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中
            titleStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
            titleStyle.setFont(titleFont);
            titleStyle.setWrapText(true);
            HSSFDataFormat format = wb.createDataFormat();
            titleStyle.setDataFormat(format.getFormat("@"));

            /**** 生成sheet1的内容 ***/
            /*** 获取企业钱包账户对账统计数据 ***/
//            Map<String, Object> map = huifuWalletReconciliationDao.getWalletReconciliationSum(dto);
            String headerTitle = "";
//            if (map == null) {
//                headerTitle = MessageFormat.format("总笔数：【{0}】笔 | 总金额：【{1}】元 | 成功笔数：【{2}】笔 | 成功金额：【{3}】元 | 失败笔数：【{4}】笔 | 失败金额：【{5}】元 | 处理中笔数：【{6}】笔 | 处理中金额：【{7}】元",
//                        0, 0, 0, 0, 0, 0, 0, 0);
            headerTitle = MessageFormat.format("总笔数：【{0}】笔",
                    detailList.size());
//            } else {
//                headerTitle = MessageFormat.format("总笔数：【{0}】笔 | 总金额：【{1}】元 | 成功笔数：【{2}】笔 | 成功金额：【{3}】元 | 失败笔数：【{4}】笔 | 失败金额：【{5}】元 | 处理中笔数：【{6}】笔 | 处理中金额：【{7}】元",
//                        map.get("totalCount"), map.get("sumAmount"), map.get("successCount"), map.get("successAmount"), map.get("errorCount"), map.get("errorAmount"), map.get("processingCount"), map.get("processingAmount"));
//            }
            /*** 填充第一行数据 ***/
            HSSFCellStyle titleStyle1 = wb.createCellStyle();
            HSSFFont titleFont1 = wb.createFont();
            titleFont1.setFontHeightInPoints((short) 11);
            titleFont1.setColor(HSSFColor.RED.index);
            titleFont1.setFontName("黑体");
            titleStyle1.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
            titleStyle1.setFont(titleFont1);
            titleStyle1.setWrapText(true);
            HSSFRow rowFirst = sheet1.createRow(0); // 第一个sheet的第一行为标题
            rowFirst.setHeight((short) (1000));
            sheet1.addMergedRegion(new CellRangeAddress(0, (short) 0, 0, 13));
            HSSFCell titleCell = rowFirst.createCell(0);
            titleCell.setCellValue(headerTitle);
            titleCell.setCellStyle(titleStyle1);

            /*** 填充第二行数据 ***/
            HSSFRow secondFirst = sheet1.createRow(1);
            String[] secondArr = {"序号", "交易流水号", "业务流水号", "交易类型", "交易状态", "创建时间", "交易金额", "交易后余额", "出账方名称", "出账方商户号", "入账方名称", "入账方商户号", "交易日期", "交易时间", "备注", "支付渠道"};
            int column;
            for (int i = 0; i < secondArr.length; i++) {
                HSSFCell cell = secondFirst.createCell(i); // 获取第二行的每个单元格
                if (i == 0) {
                    column = 1500;
                } else if (i == 5) {
                    column = 5000;
                } else if (i == 1 || i == 2 || i == 8 || i == 10) {
                    column = 10000;
                } else if (i == 14) {
                    column = 14000;
                } else {
                    column = 4000;
                }
                sheet1.setColumnWidth(i, column); // 设置每列的列宽
                sheet1.setDefaultColumnStyle(i, stringStyle); // 设置单元格格式 --文本格式
                cell.setCellStyle(titleStyle); // 文本格式
            }

            /*** 填充第二行数据 ***/
            for (int i = 0; i < secondArr.length; i++) {
                HSSFCell cell = secondFirst.createCell(i); // 获取第一行的每个单元格
                cell.setCellValue(secondArr[i]);
                cell.setCellStyle(titleStyle);
            }

            /*** 字体颜色样式 ***/
            CellStyle greenStyle = ExcelUtil.getColorStyle(wb, IndexedColors.SEA_GREEN.index);// 青绿色样式
            CellStyle redStyle = ExcelUtil.getColorStyle(wb, IndexedColors.RED.index); // 红色样式
            CellStyle blueStyle = ExcelUtil.getColorStyle(wb, IndexedColors.BLUE.index); // 红色样式
            HSSFRow row = null;
            int rowIndex = 2;
            for (HuifuWalletAccountDetail result : detailList) {
                row = sheet1.createRow(rowIndex);
                HSSFCell cell0 = row.createCell(0);
                cell0.setCellValue(rowIndex - 1);
                HSSFCell cell1 = row.createCell(1);
                cell1.setCellValue(result.getTradeFlowNo() != null ? result.getTradeFlowNo().toString() : null); // 交易流水号
                HSSFCell cell1_2 = row.createCell(2);
                cell1_2.setCellValue(result.getFlowNo() != null ? result.getFlowNo().toString() : null); // 业务流水号
                HSSFCell cell2 = row.createCell(3);
                cell2.setCellValue(result.getTradeType() != null ? result.getTradeType().toString() : null); // 银行交易类型
                HSSFCell cell3 = row.createCell(4);
                cell3.setCellValue(result.getHandStatus() != null ? result.getHandStatus().toString() : null); // 交易状态
                if (ObjectUtil.equal(result.getHandStatus(), "成功")) {
                    cell3.setCellStyle(greenStyle);
                } else if (ObjectUtil.equal(result.getHandStatus(), "失败")) {
                    cell3.setCellStyle(redStyle);
                } else {
                    cell3.setCellStyle(blueStyle);
                }
                HSSFCell cell4 = row.createCell(5);
                cell4.setCellValue(result.getCreateDate() != null ? result.getCreateDate().toString() : null); // 交易订单创建时间
                HSSFCell cell5 = row.createCell(6);
                cell5.setCellValue(result.getAmount() != null ? result.getAmount().toString() : null); // 交易金额
                cell5.setCellStyle(redStyle);
                HSSFCell cell5_7 = row.createCell(7);
                cell5_7.setCellValue(result.getBalance() != null ? result.getBalance().toString() : null); // 交易后余额
                HSSFCell cell6 = row.createCell(8);
                cell6.setCellValue(result.getAccountOutName() != null ? result.getAccountOutName().toString() : null);// 出账方户名
                HSSFCell cell7 = row.createCell(9);
                cell7.setCellValue(result.getAccountOut() != null ? result.getAccountOut().toString() : null);// 出账方账号
                HSSFCell cell8 = row.createCell(10);
                cell8.setCellValue(result.getAccountInName() != null ? result.getAccountInName().toString() : null);// 入账方户名
                HSSFCell cell9 = row.createCell(11);
                cell9.setCellValue(result.getAccountIn() != null ? result.getAccountIn().toString() : null);// 入账方账号
                HSSFCell cell10 = row.createCell(12);
                cell10.setCellValue(result.getTradeDate() != null ? result.getTradeDate().toString() : null);// 入账方银行
                HSSFCell cell11 = row.createCell(13);
                cell11.setCellValue(result.getAccountsDealDate() != null ? result.getAccountsDealDate().toString() : null);// 入账方证件号
                HSSFCell cell12 = row.createCell(14);
                cell12.setCellValue(result.getMemo() != null ? result.getMemo().toString() : null);// 备注
                HSSFCell cell13 = row.createCell(15);
                cell13.setCellValue(result.getPayChannel() != null ? result.getPayChannel().toString() : null);// 备注
                rowIndex++;
            }
            wb.write(os);
            os.close();
            wb.close();
        } catch (Exception e) {
            throw new CrmebWalletException(e.getMessage());
        } finally {
            try {
                os.close();
                wb.close();
            } catch (IOException e1) {
            }
        }
        return "0";
    }

    /**
     * <b> 获取企业钱包账户提现记录 </b>
     * @author ZXF
     * @create 2023/04/23 0023 10:37
     * @version
     * @注意事项 </b>
     */
    @Override
    public PageInfo<HuifuWalletTranslog> thisHuifuWalletTranslog(HuifuWalletTranslogDto dto) throws CrmebWalletException {
        if (StringUtils.isEmpty(dto.getUniId())) {
            throw new CrmebWalletException("企业ID不能为空");
        }
        if (dto.getPageNumber() == null) {
            throw new CrmebWalletException("第几页不能为空");
        }
        if (dto.getPageSize() == null) {
            throw new CrmebWalletException("每页多少行不能为空");
        }
        if (StringUtil.isEmpty(dto.getStartDate())) {
            throw new CrmebWalletException("开始日期不能为空");
        }
        if (StringUtil.isEmpty(dto.getEndDate())) {
            throw new CrmebWalletException("结束日期不能为空");
        }
        PageHelper.startPage(dto.getPageNumber(), dto.getPageSize());
        dto.setStartDate(dto.getStartDate().replace("-",""));
        dto.setEndDate(dto.getEndDate().replace("-",""));
        List<HuifuWalletTranslog> detailList = huifuWalletTranslogDao.selectByUniIdAndDate(dto);
        return new PageInfo(detailList);
    }


    //结合上述方法（实现多线程并发修改余额），改造成下列方法，实现某个用户的余额修改
    @Override
    public boolean modifyBalance(String uniId, BigDecimal amount,String payChannel){
        int ret = 0;
        int count=0;
        while (ret<1){
            if(count == 10){
                break;
            }
            String frozenAmount = huifuWalletAccountDao.getFrozenAmount(uniId, payChannel);
            ret = huifuWalletAccountDao.updateSumFrozenAmount(uniId,frozenAmount,(amount.add(new BigDecimal(frozenAmount))), payChannel);
            count++;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                break;
            }
        }
        if(ret == 0){
            return false;
        }
        return true;
    }
}

