package com.ai.da.service.impl;

import com.ai.da.common.utils.OrderNoUtils;
import com.ai.da.mapper.primary.RefundInfoMapper;
import com.ai.da.mapper.primary.entity.OrderInfo;
import com.ai.da.mapper.primary.entity.RefundInfo;
import com.ai.da.service.OrderInfoService;
import com.ai.da.service.RefundInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.gson.Gson;
import com.stripe.model.Charge;
import com.stripe.model.Refund;
import io.netty.util.internal.StringUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDateTime;
import java.util.*;

@Service
public class RefundInfoServiceImpl extends ServiceImpl<RefundInfoMapper, RefundInfo> implements RefundInfoService {

    @Resource
    private OrderInfoService orderInfoService;

    /**
     * 根据订单号创建退款订单
     * @param orderNo
     * @return
     */
    @Override
    public RefundInfo createRefundByOrderNo(String orderNo, String reason) {

        //根据订单号获取订单信息
        OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(orderNo);

        //根据订单号生成退款订单
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setOrderNo(orderNo);//订单编号
        refundInfo.setRefundNo(OrderNoUtils.getRefundNo());//退款单编号
        refundInfo.setTotalFee(orderInfo.getTotalFee());//原订单金额(元)
        refundInfo.setRefund(orderInfo.getTotalFee());//退款金额(元)
        refundInfo.setReason(reason);//退款原因

        //保存退款订单
        baseMapper.insert(refundInfo);

        return refundInfo;
    }

    /**
     * 记录退款记录
     * @param content
     */
    @Override
    public void updateRefund(String content) {

        //将json字符串转换成Map
        Gson gson = new Gson();
        Map<String, String> resultMap = gson.fromJson(content, HashMap.class);

        //根据退款单编号修改退款单
        QueryWrapper<RefundInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("refund_no", resultMap.get("out_refund_no"));

        //设置要修改的字段
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setRefundId(resultMap.get("refund_id"));//微信支付退款单号

        //查询退款和申请退款中的返回参数
        if(resultMap.get("status") != null){
            refundInfo.setRefundStatus(resultMap.get("status"));//退款状态
            refundInfo.setContentReturn(content);//将全部响应结果存入数据库的content字段
        }
        //退款回调中的回调参数
        if(resultMap.get("refund_status") != null){
            refundInfo.setRefundStatus(resultMap.get("refund_status"));//退款状态
            refundInfo.setContentNotify(content);//将全部响应结果存入数据库的content字段
        }

        //更新退款单
        baseMapper.update(refundInfo, queryWrapper);
    }

    /**
     * 找出申请退款超过minutes分钟并且未成功的退款单
     * @param minutes
     * @return
     */
    @Override
    public List<RefundInfo> getNoRefundOrderByDuration(int minutes) {

        //minutes分钟之前的时间
        Instant instant = Instant.now().minus(Duration.ofMinutes(minutes));

        QueryWrapper<RefundInfo> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("refund_status", WxRefundStatus.PROCESSING.getType());
        queryWrapper.le("create_time", instant);
        List<RefundInfo> refundInfoList = baseMapper.selectList(queryWrapper);
        return refundInfoList;
    }

    /**
     * 根据订单号创建退款订单
     * @param orderNo
     * @return
     */
    @Override
    public RefundInfo createRefundByOrderNoForAliPay(String orderNo, String reason) {

        //根据订单号获取订单信息
        OrderInfo orderInfo = orderInfoService.getOrderByOrderNo(orderNo);

        //根据订单号生成退款订单
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setOrderNo(orderNo);//订单编号
        refundInfo.setRefundNo(OrderNoUtils.getRefundNo());//退款单编号

        refundInfo.setTotalFee(orderInfo.getTotalFee());//原订单金额(元)
        refundInfo.setRefund(orderInfo.getTotalFee());//退款金额(元)
        refundInfo.setReason(reason);//退款原因

        //保存退款订单
        baseMapper.insert(refundInfo);

        return refundInfo;
    }

    /**
     * 更新退款记录
     * @param refundNo
     * @param content
     * @param refundStatus
     */
    @Override
    public void updateRefundForAliPay(String refundNo, String content, String refundStatus) {

        //根据退款单编号修改退款单
        QueryWrapper<RefundInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("refund_no", refundNo);

        //设置要修改的字段
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setRefundStatus(refundStatus);//退款状态
        refundInfo.setContentReturn(content);//将全部响应结果存入数据库的content字段

        //更新退款单
        baseMapper.update(refundInfo, queryWrapper);

    }

    @Override
    public void updateRefundForPayPal(Long id, String refundId,String content, String refundStatus) {

        //根据退款单编号修改退款单
//        QueryWrapper<RefundInfo> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("order_no", orderNo);

        //设置要修改的字段
        RefundInfo refundInfo = new RefundInfo();
        refundInfo.setId(id);
        refundInfo.setRefundNo(null);
        refundInfo.setRefundId(refundId);
        refundInfo.setRefundStatus(refundStatus);//退款状态
        refundInfo.setContentReturn(content);//将全部响应结果存入数据库的content字段

        //更新退款单
//        baseMapper.update(refundInfo, queryWrapper);
        baseMapper.updateById(refundInfo);
    }

    public List<RefundInfo> getByChargeId(String chargeId){
        List<RefundInfo> refundInfoList = baseMapper.selectList(new QueryWrapper<RefundInfo>().eq("charge_id", chargeId));
        // 判断当前已退款的金额是否全部退完（针对多次部分退款的情况）
        if (refundInfoList.isEmpty()){
            return new ArrayList<>();
        }else {
            return refundInfoList;
        }
    }

    public RefundInfo getByRefundId(String refundId){
        return baseMapper.selectOne(new QueryWrapper<RefundInfo>().eq("refund_id", refundId));
    }

    public RefundInfo createRefundForStripe(Refund refund){
        // 先确认这个回调是否已经被记录
        RefundInfo refundInfo = getByRefundId(refund.getId());
        if (Objects.isNull(refundInfo)){
            refundInfo = new RefundInfo();
            refundInfo.setRefundId(refund.getId());
            refundInfo.setChargeId(refund.getCharge());
            refundInfo.setRefund(refund.getAmount() / 100f);
            refundInfo.setReason(refund.getReason());
            refundInfo.setRefundStatus(refund.getStatus());
            refundInfo.setCreateTime(LocalDateTime.now());
            baseMapper.insert(refundInfo);
        }
        return refundInfo;
    }

    public RefundInfo updateRefundStatusForStripe(Refund refund){
        RefundInfo refundInfo = getByRefundId(refund.getId());
        if (Objects.isNull(refundInfo)){
            return null;
        }
        if (!refundInfo.getRefundStatus().equals(refund.getStatus())){
            refundInfo.setRefundStatus(refund.getStatus());
            refundInfo.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(refundInfo);
        }
        return refundInfo;
    }

    public RefundInfo updateRefundForStripe(Charge charge){
        List<RefundInfo> refundInfoList = getByChargeId(charge.getId());
        if (!refundInfoList.isEmpty()){
            RefundInfo refundInfo = refundInfoList.get(refundInfoList.size() - 1);
            if (StringUtil.isNullOrEmpty(refundInfo.getOrderNo())){
                String orderNo = charge.getDescription().replace("AiDA - ", "");
                refundInfo.setOrderNo(orderNo);
                refundInfo.setTotalFee(charge.getAmount() / 100f);
                refundInfo.setUpdateTime(LocalDateTime.now());
                baseMapper.updateById(refundInfo);
                return refundInfo;
            }
        }
        return null;
    }
}
