package com.jeequan.jeepay.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeequan.jeepay.core.cache.RedisUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.params.zftpay.ZftpayIsvParams;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.db.entity.PayAlizftSettRecord;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.service.mapper.PayAlizftSettRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 直付通二级商户结算记录表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2021-12-06
 */
@Service
@Slf4j
public class PayAlizftSettRecordService extends ServiceImpl<PayAlizftSettRecordMapper, PayAlizftSettRecord> {

    @Autowired
    SysLegalDayService sysLegalDayService;

    /** 初始化结算订单 **/
    public PayAlizftSettRecord initWaitRecord(PayOrder payOrder, ZftpayIsvParams isvParams, String subMchId, Date payOrderSuccessTime) {

        String payOrderId = payOrder.getPayOrderId();

        // 记录是否已存在
        PayAlizftSettRecord settRecord = baseMapper.selectOne(PayAlizftSettRecord.gw()
                .eq(PayAlizftSettRecord::getPayOrderId, payOrderId)
                .eq(PayAlizftSettRecord::getChannelOrderNo, payOrder.getChannelOrderNo())
        );
        if (settRecord != null) {
            log.info("结算记录已存在 settRecord：{}", settRecord);
            return settRecord;
        }

        PayAlizftSettRecord record = new PayAlizftSettRecord();
        record.setSettleNo(SeqKit.genFlowNo("ZFT"));
        record.setAppId(payOrder.getAppId());
        record.setMchNo(payOrder.getMchNo());
        record.setMchName(payOrder.getMchName());
        record.setAgentNo(payOrder.getAgentNo());
        record.setIsvNo(payOrder.getIsvNo());

        record.setPayOrderId(payOrderId);
        record.setPayOrderAmount(payOrder.getAmount());
        record.setPayOrderSubject(payOrder.getSubject());
        record.setChannelOrderNo(payOrder.getChannelOrderNo()); // 渠道订单号
        record.setSubMchId(subMchId); // 二级商户ID

        // 结算时间，根据服务商配置可能是D0  T0  D1  T1  D2  T2 ....
        // 结算时间 = 支付成功时间 + (D+x) + 30s
        record.setSettTime(this.genSettTime(payOrderSuccessTime, isvParams));

        // date为空的话： 业务侧直接延迟30s

        //未结算状态
        record.setState(PayAlizftSettRecord.ZFT_SETT_STATUS_NOT);

        save(record);
        return record;
    }

    /**
     * 结算时间，null表示实时结算
     **/
    private Date genSettTime(Date payOrderSuccessTime, ZftpayIsvParams isvParams) {
        Date finalDate = null;

        // 未配置结算时间 或 结算日期为0，则实时结算
        if (StringUtils.isBlank(isvParams.getSettDayType()) || isvParams.getSettDay() <= 0) {
            // 时间 + 30s
            return DateUtil.offsetSecond(payOrderSuccessTime, 30).toJdkDate();
        }

        if ("D".equals(isvParams.getSettDayType())) {
            finalDate = DateUtil.offsetDay(payOrderSuccessTime, isvParams.getSettDay());

        } else if ("T".equals(isvParams.getSettDayType())) {

            // 查询redis缓存
            String redisTnDateStr = RedisUtil.getString(CS.getCacheKeyDateTn(DateUtil.formatDate(payOrderSuccessTime), isvParams.getSettDay()));
            if (StringUtils.isNotBlank(redisTnDateStr)) {
                // redis存储的为YYYY-MM-DD，应拼接订单的HH:MM:SS
                finalDate = DateUtil.parseDateTime(redisTnDateStr + " " + DateUtil.formatTime(payOrderSuccessTime));

                // 时间 + 30s
                return DateUtil.offsetSecond(finalDate, 30).toJdkDate();
            }

            finalDate = sysLegalDayService.getTnDate(payOrderSuccessTime, isvParams.getSettDay());

            // redis缓存T+N时间，有效期1天
            RedisUtil.setString(CS.getCacheKeyDateTn(DateUtil.formatDate(payOrderSuccessTime), isvParams.getSettDay()), DateUtil.formatDate(finalDate), 1, TimeUnit.DAYS);
        }

        // 时间 + 30s
        return DateUtil.offsetSecond(finalDate, 30).toJdkDate();
    }

    /** 更新结算订单状态及发起返回信息 **/
    public int updateWait2StatusAndCountAndMsg(PayAlizftSettRecord dbRecord, String thisApplyMsg, Byte updatedStatus) {
        dbRecord.appendApplyInfo(dbRecord.getApplyInfo(), thisApplyMsg);
        Map paramsMap = new HashMap<>();
        paramsMap.put("settleNo", dbRecord.getSettleNo());
        paramsMap.put("state", updatedStatus);
        paramsMap.put("applyInfo", dbRecord.getApplyInfo());
        return baseMapper.updateWait2StatusAndCountAndMsg(paramsMap);
    }

    /** 查询直付通结算记录列表 **/
    public IPage<PayAlizftSettRecord> listByPage(IPage iPage, PayAlizftSettRecord settRecord){
        LambdaQueryWrapper<PayAlizftSettRecord> wrapper = PayAlizftSettRecord.gw();
        wrapper.eq(StringUtils.isNotEmpty(settRecord.getSettleNo()), PayAlizftSettRecord::getSettleNo, settRecord.getSettleNo());
        wrapper.eq(StringUtils.isNotEmpty(settRecord.getPayOrderId()), PayAlizftSettRecord::getPayOrderId, settRecord.getPayOrderId());
        wrapper.eq(StringUtils.isNotEmpty(settRecord.getChannelOrderNo()), PayAlizftSettRecord::getChannelOrderNo, settRecord.getChannelOrderNo());
        wrapper.eq(StringUtils.isNotEmpty(settRecord.getSubMchId()), PayAlizftSettRecord::getSubMchId,settRecord.getSubMchId());
        wrapper.eq(StringUtils.isNotEmpty(settRecord.getIsvNo()), PayAlizftSettRecord::getIsvNo, settRecord.getIsvNo());
        wrapper.eq(StringUtils.isNotEmpty(settRecord.getAgentNo()), PayAlizftSettRecord::getAgentNo, settRecord.getAgentNo());
        wrapper.eq(StringUtils.isNotEmpty(settRecord.getMchNo()), PayAlizftSettRecord::getMchNo, settRecord.getMchNo());
        wrapper.eq(settRecord.getState() != null, PayAlizftSettRecord::getState, settRecord.getState());
        // 时间范围条件
        Date[] dateRange = settRecord.buildQueryDateRange();
        if (dateRange[0] != null) {
            wrapper.ge(PayAlizftSettRecord::getCreatedAt, dateRange[0]);
        }
        if (dateRange[1] != null) {
            wrapper.le(PayAlizftSettRecord::getCreatedAt, dateRange[1]);
        }

        // 批量结算，只查询状态为【待结算、结算待重试、结算失败】的订单
        if (settRecord.extv().getByteValue("isBatchSett") == CS.YES) {
            wrapper.in(PayAlizftSettRecord::getState, Arrays.asList(PayAlizftSettRecord.ZFT_SETT_STATUS_NOT, PayAlizftSettRecord.ZFT_SETT_STATUS_FAIL,
                    PayAlizftSettRecord.ZFT_SETT_STATUS_WAIT_RETRY));
        }

        wrapper.orderByDesc(PayAlizftSettRecord::getCreatedAt);
        return page(iPage, wrapper);
    }


    /**
     * 根据支付订单查询结算记录
     * 根据： 订单查询。
     **/
    public PayAlizftSettRecord getByPayOrder(String payOrderId, String channelOrderNo) {

        return getOne(PayAlizftSettRecord.gw()
                .eq(PayAlizftSettRecord::getPayOrderId, payOrderId)
                .eq(StringUtils.isNotEmpty(channelOrderNo), PayAlizftSettRecord::getChannelOrderNo, channelOrderNo), false);
    }

}
