package com.xunwang.payment.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xunwang.commonutils.R;
import com.xunwang.payment.entity.InviteInfo;
import com.xunwang.payment.entity.OrderInfo;
import com.xunwang.payment.enums.OrderStatus;
import com.xunwang.payment.feign.MsgFeign;
import com.xunwang.payment.feign.UserFeign;
import com.xunwang.payment.mapper.OrderInfoMapper;
import com.xunwang.payment.service.OrderInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xunwang.payment.util.OrderNoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.format.annotation.DateTimeFormat;
import com.xunwang.payment.util.OrderNoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.time.format.DateTimeFormatterBuilder;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.time.Instant;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author Long
 * @since 2023-02-23
 */
@Service
@Slf4j
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private UserFeign userFeign;

    @Resource
    private MsgFeign msgFeign;

    @Override
    public OrderInfo createOrderByInviteId(String inviteId) {
        // 查找已存在但未支付的订单
        OrderInfo orderInfo = baseMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getInviteId, inviteId).eq(OrderInfo::getStatus, OrderStatus.NOTPAY.getType()));
        if (orderInfo != null) {
            return orderInfo;
        }

        // 获取邀请信息
        InviteInfo inviteInfo = baseMapper.selectInviteInfo(inviteId);
        String identity = inviteInfo.getIdentity();
        String teacherName = "";
        String teacherId = "";
        String studentName = "";
        String studentId = "";
        String uid = null;
        if ("教员".equals(identity)) {
            uid = inviteInfo.getToUid();
            teacherId = inviteInfo.getFromUid();
            teacherName = inviteInfo.getFromUname();
            studentName = inviteInfo.getToUname();
            studentId = inviteInfo.getToUid();
        }
        if ("学员".equals(identity)) {
            uid = inviteInfo.getFromUid();
            teacherId = inviteInfo.getToUid();
            teacherName = inviteInfo.getToUname();
            studentName = inviteInfo.getFromUname();
            studentId = inviteInfo.getFromUid();
        }
        // 获取学生recommendUid
        R recommendR = userFeign.getRecommendUidByUid(studentId);
        String recommendUid = (String)recommendR.getData().get("recommendUid");

        // 获取openid
        String openid = baseMapper.getOpenIdByUid(uid);

        // 生成订单
        orderInfo = new OrderInfo();
        orderInfo.setRequireDetail("无");
        orderInfo.setFromUid(inviteInfo.getFromUid());
        orderInfo.setToUid(inviteInfo.getToUid());
        orderInfo.setRequireId(inviteInfo.getRequireId());
        orderInfo.setCourseId(inviteInfo.getCourseId());
        orderInfo.setOpenId(openid);
        orderInfo.setFromUname(inviteInfo.getFromUname());
        orderInfo.setToUname(inviteInfo.getToUname());
        orderInfo.setOrderId(OrderNoUtils.getOrderNo());
        orderInfo.setRequireSalary(inviteInfo.getRequireSalary().multiply(new BigDecimal(100)));
        orderInfo.setInviteId(inviteInfo.getId());
        orderInfo.setDatetime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));

        orderInfo.setRecommendUid(recommendUid);
        orderInfo.setTeacherName(teacherName);
        orderInfo.setStatus("未支付");
        orderInfo.setTeacherId(teacherId);
        orderInfo.setStudentId(studentId);
        orderInfo.setStudentName(studentName);

        int insert = baseMapper.insert(orderInfo);

        // 支付倒计时存入redis中
        stringRedisTemplate.opsForValue().set("countdown:" + orderInfo.getOrderId(), "1", 15, TimeUnit.MINUTES);
        return orderInfo;
    }

    @Override
    public void savePerpayId(String orderNo, String prepayId) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setPrepayId(prepayId);
        baseMapper.update(orderInfo, new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderId, orderNo));
    }

    @Override
    public List<OrderInfo> listOrderByCreateTimeDesc(String openId) {

        List<OrderInfo> list = baseMapper.selectList(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOpenId, openId).orderByDesc(OrderInfo::getDatetime));
        return list;
    }

    @Override
    public String getOrderStatus(String orderNo) {
        OrderInfo orderInfo = baseMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderId, orderNo));

        // 防止被删除的订单的回调通知的调用
        if (orderInfo == null) {
            return null;
        }
        return orderInfo.getStatus();
    }

    /**
     * 根据订单编号更新订单状态
     * @param orderNo
     * @param orderStatus
     */
    @Override
    public void updateStatusByOrderNo(String orderNo, OrderStatus orderStatus) {
        log.info("更新订单状态 ===> {}", orderStatus.getType());
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getOrderId, orderNo);
        OrderInfo orderInfo = getOne(wrapper);
        orderInfo.setStatus(orderStatus.getType());
        orderInfo.setOrderId(orderNo);

        // 更新课程和需求的上下架以及是否锁住
        if (orderStatus.equals(OrderStatus.SUCCESS)) {
            // 佣金
            BigDecimal requireSalary = orderInfo.getRequireSalary();
            BigDecimal rate = new BigDecimal("0.6");
            BigDecimal commissionDecimal = requireSalary.multiply(rate).setScale(0, RoundingMode.DOWN);
            BigDecimal recoCommissionDecimal = commissionDecimal.multiply(rate).setScale(0, RoundingMode.DOWN);
            orderInfo.setCommission(commissionDecimal).setRecoCommission(recoCommissionDecimal);
            // 修改课程和需求成交,下架
            String requireId = orderInfo.getRequireId();
            String courseId = orderInfo.getCourseId();
            baseMapper.updateCourseStatus(courseId);
            baseMapper.updateRequireStatus(requireId);
        } else {
            // 修改课程和需求未成交,未锁
            String requireId = orderInfo.getRequireId();
            String courseId = orderInfo.getCourseId();
            baseMapper.updateRefundCourseStatus(courseId);
            baseMapper.updateRefundRequireStatus(requireId);
            // 佣金设为0
            BigDecimal bigDecimal = new BigDecimal("0");
            orderInfo.setCommission(bigDecimal).setRecoCommission(bigDecimal);
        }
        update(orderInfo, wrapper);
    }

    @Override
    public List<OrderInfo> getNoPayOrderByDuration(int minutes) {
        // minutes分钟之前的时间
        Instant instant = Instant.now().minus(Duration.ofMinutes(minutes));

        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setStatus(OrderStatus.NOTPAY.getType());
        orderInfo.setDatetime(String.valueOf(instant));
        List<OrderInfo> orderInfoList = baseMapper.selectList(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getStatus, OrderStatus.NOTPAY.getType())
                        .isNotNull(OrderInfo::getPrepayId)
                        .le(OrderInfo::getDatetime, orderInfo.getDatetime()));

        return orderInfoList;
    }

    /**
     * 查询支付中本地订单状态
     * @param orderId
     */
    @Override
    public R queryOrderStatus(String orderId) {
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getOrderId, orderId);
        OrderInfo one = getOne(wrapper);
        String status = one.getStatus();
        String studentId = one.getStudentId();
        if (OrderStatus.SUCCESS.getType().equals(status)) {
            // 推送支付成功消息
            msgFeign.notifyPaymentSuccess(studentId, orderId);
            // 删除redis的倒计时键
            stringRedisTemplate.delete("countdown:" + orderId);

            return R.ok().message("支付成功");
        }
        return R.ok().message("支付中");
    }

    /**
     * 查询本地订单是否退款
     * @param orderId
     * @return
     */
    @Override
    public R queryIsRefundOrder(String orderId) {
        LambdaQueryWrapper<OrderInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(OrderInfo::getOrderId, orderId);
        OrderInfo one = getOne(wrapper);
        String status = one.getStatus();
        if ("已退款".equals(status)) {
            update(one, wrapper);
            return R.ok().message("已退款");
        }
        return R.ok().message("退款中");
    }
}
