package com.jeequan.jeepay.thirdparty.channel.sxfpay;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.csv.CsvData;
import cn.hutool.core.text.csv.CsvRow;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.CheckBatch;
import com.jeequan.jeepay.core.model.bill.ChannelBill;
import com.jeequan.jeepay.core.model.bill.ChannelBillRQ;
import com.jeequan.jeepay.core.model.bill.ChannelBillRS;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.IsvParams;
import com.jeequan.jeepay.core.model.params.sxfpay.SxfpayIsvParams;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.ExcelUtil;
import com.jeequan.jeepay.db.entity.CheckChannelBill;
import com.jeequan.jeepay.thirdparty.channel.AbstractBillDownloadService;
import com.jeequan.jeepay.thirdparty.channel.sxfpay.model.ReqMethod;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.zip.ZipEntry;

/*
* 随行付 对账单下载
*/
@Slf4j
@Service
public class SxfpayBillDownloadService extends AbstractBillDownloadService {

    @Override
    public String getIfCode() {
        return CS.IF_CODE.SXFPAY;
    }

    /**
     * billType 对账单类型，枚举值
     * 取值范围：
     * 00 交易
     * 01 结算
     * 02 分账
     * 03 硬件交易
     * 04 微校交易
     * 05 转账
     */
    @Override
    public ChannelBillRS convertStandardBill(ChannelBillRQ channelBillRQ, MchAppConfigContext mchAppConfigContext, Date billDate, String ifCode){

        String logPrefix = "【随行付对账单下载】";
        SxfpayIsvParams isvParams = (SxfpayIsvParams) channelBillRQ.getIsvParams();
        ChannelBillRS channelBillRes = new ChannelBillRS();
        String channelMchNo = channelBillRQ.getChannelMchNo(); // 渠道商户号
        // 账单文件流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            JSONObject bizContent = new JSONObject();
            bizContent.put("billDate",DateUtil.format(DateUtil.offsetDay(billDate,1), DatePattern.PURE_DATE_PATTERN));
            bizContent.put("billType","00");
            //获取随行付的对账单
            JSONObject response = SxfpayKit.reqApi(ReqMethod.Method.CHECK_GET_FILE, isvParams, bizContent);
            // 下载对账单，写入文件输出流
            HttpUtil.download(response.getString("downloadUrl"), byteArrayOutputStream, false);
            // 上传oss
            String url = upload2Oss(ifCode, channelMchNo, billDate, ".csv", IoUtil.toStream(byteArrayOutputStream));
            // 生成附带对账文件下载地址的解析成功的批次
            CheckBatch checkBatch = genReleaseSuccessCheckBatch(ifCode, billDate, channelMchNo, url);
            // 渠道账单列表
            List<ChannelBill> channelBillList = new ArrayList<>();
            // 渠道总退款金额
            long channelTotalRefundAmount = 0;
            // 读取对账单 csv文件
            CsvData csvRows = ExcelUtil.readCsvData(byteArrayOutputStream, CharsetUtil.CHARSET_UTF_8);
            List<CsvRow> rows = csvRows.getRows();
            // 遍历行
            for (int i = 1; i < rows.size(); i++) {
                CsvRow csvRow = rows.get(i);
                // getRawList返回一个List列表，列表的每一项为CSV中的一个单元格
                List<String> rawList = csvRow.getRawList();
                if (rawList.size() > 22) {
                    String thirdMchNo = rawList.get(0).trim();
                    ChannelBill channelBill = new ChannelBill();
                    channelBill.setBatchNo(checkBatch.getBatchNo());
                    channelBill.setBillDate(billDate);
                    channelBill.setIfCode(ifCode);
                    channelBill.setChannelMchNo(thirdMchNo);
                    channelBill.setChannelOrderNo(rawList.get(3).trim());
                    channelBill.setChannelAmount(Math.abs(AmountUtil.convertDollar2CentLong(rawList.get(9).trim())));
                    channelBill.setChannelFeeAmount(Math.abs(AmountUtil.convertDollar2CentLong(rawList.get(11).trim())));
                    channelBill.setChannelSuccessAt(DateUtil.parse(rawList.get(14).trim(),"yyyyMMdd HH:mm:ss"));
                    if (StringUtils.equals(rawList.get(7).trim(), "00")) {
                        channelBill.setOrderId(rawList.get(2).trim());
                        channelBill.setBillType(CheckChannelBill.BILL_TYPE_PAY);
                        channelBill.setChannelState((byte) 2);
                    }else if (StringUtils.equals(rawList.get(7).trim(), "01")) {
                        channelBill.setOrderId(rawList.get(2).trim());
                        channelBill.setBillType(CheckChannelBill.BILL_TYPE_REFUND);
                        channelBill.setChannelState((byte) 5);
                        channelBill.setOrgPayOrderId(rawList.get(4).trim());
                        channelTotalRefundAmount += channelBill.getChannelAmount();
                    }
                    channelBillList.add(channelBill);
                }
            }
            checkBatch.setChannelTotalRefundAmount(channelTotalRefundAmount);
            checkBatch.setChannelTotalAmount(checkBatch.getChannelTotalAmount() + Math.abs(channelTotalRefundAmount));
            channelBillRes.setCheckBatch(checkBatch);
            channelBillRes.setChannelBillList(channelBillList);
            return channelBillRes;
        }catch (Exception e) {
            log.error("{}, 解析对账文件失败，", logPrefix, e);
            channelBillRes.setCheckBatch(genReleaseFailCheckBatch(ifCode, billDate, channelMchNo, e.getMessage()));
            return channelBillRes;
        }finally {
            IoUtil.close(byteArrayOutputStream);
        }
    }
}
