package com.kxs.product.biz.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil;
import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kxs.common.core.constant.CommonConstants;
import com.kxs.common.core.exception.GlobalCustomerException;
import com.kxs.common.core.util.R;
import com.kxs.common.mq.handlers.IMQSender;
import com.kxs.common.pay.enums.PayPlatformEnum;
import com.kxs.common.pay.factory.PaymentFactory;
import com.kxs.common.pay.model.PayRequest;
import com.kxs.common.pay.model.PayResponse;
import com.kxs.common.pay.model.YuePayMessage;
import com.kxs.common.security.util.SecurityUtils;
import com.kxs.product.api.amqp.rabbit.RabbitShopTimeoutQueueMQ;
import com.kxs.product.api.dto.kxsapp.shop.GoodsSubmitDTO;
import com.kxs.product.api.dto.kxsapp.shop.PayOrderDTO;
import com.kxs.product.api.model.*;
import com.kxs.product.api.vo.kxsapp.shop.*;
import com.kxs.product.biz.constant.enums.KxsShopEnum;
import com.kxs.product.biz.constant.enums.ProductErrorTypeEnum;
import com.kxs.product.biz.mapper.*;
import com.kxs.product.biz.service.KxsShopOrderService;
import com.kxs.user.api.feign.RemoteKxsUserService;
import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 商城订单表(KxsShopOrder)表服务实现类
 *
 * @author 系统
 * @since 2023-12-20 10:09:35
 */
@Service("kxsShopOrderService")
@RequiredArgsConstructor
@Slf4j
public class KxsShopOrderServiceImpl extends ServiceImpl<KxsShopOrderMapper, KxsShopOrder> implements KxsShopOrderService {

    private final KxsShopGoodsMapper goodsMapper;

    private final KxsShopOrderInfoMapper orderInfoMapper;

    private final RemoteKxsUserService remoteKxsUserService;

    private final PaymentFactory paymentFactory;
    private final KxsShopGoodsSkuMapper kxsShopGoodsSkuMapper;
    private final KxsTicketMapper kxsTicketMapper;
    private final IMQSender mqSender;
    @Override
    @Transactional(rollbackFor = Exception.class)
    public R submitOrder(GoodsSubmitDTO param) {

        Long userId = SecurityUtils.getUser().getId();

        //订单号
        String orderSn = CommonConstants.KXS_SHOP_PREFIX + IdUtil.getSnowflakeNextIdStr();

        KxsShopOrder order = new KxsShopOrder();
        //参数赋值
        BeanUtils.copyProperties(param, order);
        order.setUserId(userId);
        order.setOrderSn(orderSn);
        //支付金额
        order.setPayPrice(order.getTotalPrice());
        baseMapper.insert(order);

        //查询商品
        KxsShopGoods goods = goodsMapper.selectById(param.getGoodsId());
        Optional.ofNullable(goods).orElseThrow(() -> new GlobalCustomerException("商品不存在"));
        //查询商品sku
        KxsShopGoodsSku kxsShopGoodsSku = kxsShopGoodsSkuMapper.selectOne(Wrappers.<KxsShopGoodsSku>query().lambda().eq(KxsShopGoodsSku::getGoodId, goods.getId()));
        if (kxsShopGoodsSku != null){
            //当sku库存不为null时需做存量校验
            if (kxsShopGoodsSku.getStockNum() != null && kxsShopGoodsSku.getStockNum() != -1){
                int i = kxsShopGoodsSku.getStockNum() - param.getNumber();
                if(i < 0){
                    return R.failed("当前库存不足");
                }
                kxsShopGoodsSku.setStockNum(i);
                //修改库存
                kxsShopGoodsSkuMapper.updateById(kxsShopGoodsSku);
            }
            //校验是否存在起购以及限购数量校验
            if (kxsShopGoodsSku.getStartByCount() != null && kxsShopGoodsSku.getStartByCount() != 0){
                boolean b = kxsShopGoodsSku.getStartByCount() > param.getNumber();
                if (b){
                    return R.failed("该商品最低" + kxsShopGoodsSku.getStartByCount() + "件起购");
                }
            }else if (kxsShopGoodsSku.getLimitCount() != null && kxsShopGoodsSku.getLimitCount() != 0){
                boolean b = kxsShopGoodsSku.getLimitCount() < param.getNumber();
                if (b){
                    return R.failed("该商品每人最多购买" + kxsShopGoodsSku.getLimitCount() + "件");
                }
            }
        }
        //订单详情
        KxsShopOrderInfo orderInfo = new KxsShopOrderInfo();
        orderInfo.setNumber(param.getNumber());
        orderInfo.setGoodsId(param.getGoodsId());
        orderInfo.setSkuId(param.getSkuId());
        orderInfo.setSpecifications(param.getSpecifications());
        orderInfo.setGoodsName(goods.getGoodsName());
        orderInfo.setGoodsPrice(goods.getPrice());
        orderInfo.setPicUrl(goods.getPicUrl());
        orderInfo.setOrderId(order.getId());
        orderInfoMapper.insert(orderInfo);

        //发送订单延时取消消息
        RabbitShopTimeoutQueueMQ.MsgEntity msgEntity = new RabbitShopTimeoutQueueMQ.MsgEntity();
        BeanUtils.copyProperties(order,msgEntity);
        mqSender.send(RabbitShopTimeoutQueueMQ.build(msgEntity),60*20);
        return R.ok(order.getId());

    }

    @Override
    public ShopOrderDetailVO getByOrderId(Integer orderId) {

        KxsShopOrder order = baseMapper.selectById(orderId);
        if(order == null){
            return null;
        }
        ShopOrderDetailVO shopOrderDetailVO = new ShopOrderDetailVO();
        BeanUtils.copyProperties(order, shopOrderDetailVO);

        List<KxsShopOrderInfo> orderInfos = orderInfoMapper.selectList(Wrappers.<KxsShopOrderInfo>lambdaQuery()
                .eq(KxsShopOrderInfo::getOrderId, orderId));

        orderInfos.forEach(item -> {
            ShopOrderInfoListVO infoListVO = new ShopOrderInfoListVO();
            BeanUtils.copyProperties(item, infoListVO);
            shopOrderDetailVO.getGoodsList().add(infoListVO);
        });

        return shopOrderDetailVO;
    }

    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public R payOrder(PayOrderDTO param) {

        if(param.getId() == null){
            return R.failed(ProductErrorTypeEnum.ORDER_EMPTY.getDescription());
        }
        if(param.getPayType() == null){
            return R.failed("请选择支付方式");
        }
        KxsShopOrder order = baseMapper.selectById(param.getId());
        if(order == null){
            return R.failed(ProductErrorTypeEnum.ORDER_EMPTY.getDescription());
        }
        if(!Objects.equals(order.getStatus(), KxsShopEnum.ORDER_NO_PAY.getType())){
            return R.failed(ProductErrorTypeEnum.ORDER_STATUS_ERROR.getDescription());
        }
        List<KxsShopOrderInfo> kxsShopOrderInfos = orderInfoMapper.selectList(Wrappers.<KxsShopOrderInfo>lambdaQuery().eq(KxsShopOrderInfo::getOrderId, order.getId()));
        String subject = kxsShopOrderInfos.stream().map(KxsShopOrderInfo::getGoodsName).collect(Collectors.joining(","));

        //支付宝支付
        if(param.getPayType().equals(KxsShopEnum.ALI_PAY.getType())){
            return this.aliPay(order, subject);
        }

        //余额支付
        if(param.getPayType().equals(KxsShopEnum.YUE_PAY.getType())){
            Optional.ofNullable(param.getPayPwd()).orElseThrow(() -> new GlobalCustomerException("请输入支付密码"));
            //校验支付密码
            R<Boolean> booleanR = remoteKxsUserService.checkPayPwd(param.getPayPwd());
            if(booleanR.getStatus() != 1 || !booleanR.getData()){
                return R.failed("支付密码错误");
            }

            LambdaUpdateWrapper<KxsShopOrder> lambdaUpdateWrapper = Wrappers.<KxsShopOrder>lambdaUpdate().eq(KxsShopOrder::getId, param.getId());
            lambdaUpdateWrapper.set(KxsShopOrder::getPayType, param.getPayType())
                    .set(KxsShopOrder::getGetMode, param.getGetMode())
                    .set(KxsShopOrder::getRemark, param.getRemark());

            PayRequest payReq = new PayRequest();
            payReq.setPayTypeEnum(PayPlatformEnum.ALIPAY);
            payReq.setOutTradeNo(order.getOrderSn());
            payReq.setSubject(subject);
            payReq.setTotalAmount(order.getPayPrice().doubleValue());
            try {
                PayResponse payResponse = paymentFactory.getPayService(PayPlatformEnum.YUEPAY.getType()).appPay(payReq);

                YuePayMessage payMessage = BeanUtil.toBean(payResponse, YuePayMessage.class);
                if (payMessage != null) {
                    //支付成功
                    lambdaUpdateWrapper.set(KxsShopOrder::getStatus, KxsShopEnum.ORDER_NO_SEND.getType());
                    lambdaUpdateWrapper.set(KxsShopOrder::getPayTime, LocalDateTime.now());
                }else{
                    return R.failed(payResponse.getResult());
                }
            } catch (AlipayApiException e) {
                throw new GlobalCustomerException("余额支付异常");
            }
            //修改订单信息
            this.update(lambdaUpdateWrapper);
            //TODO 余额走支付接下来的逻辑
            //根据订单详情依次处理
            for (KxsShopOrderInfo kxsShopOrderInfo : kxsShopOrderInfos) {
                switch(kxsShopOrderInfo.getGoodsId()){
                    case 10:
                        //电签兑换券流程
                        List<KxsTicket> kxsTickets = kxsTicketMapper.selectList(new Page<>(1, 3), Wrappers.<KxsTicket>query().lambda()
                                .eq(KxsTicket::getUserId, 0)
                                .eq(KxsTicket::getTicketType, 0)
                                .eq(KxsTicket::getStatus, 0));
                        if (kxsTickets.size() < 3){
                            throw new GlobalCustomerException("劵码库存不足");
                        }
                        for (KxsTicket kxsTicket : kxsTickets) {
                            kxsTicket.setUpdateTime(LocalDateTime.now());
                            kxsTicket.setStatus(0);
                            kxsTicket.setUserId(Math.toIntExact(order.getUserId()));
                            kxsTicket.setTicketAllotPath(kxsTicket.getTicketAllotPath() + order.getUserId() + "," );
                            kxsTicket.setOrderId(order.getId());
                            //todo 盟主 合伙人标记
//                            kxsTicket.setLeaderId();
//                            kxsTicket.setPartnerId();
                            kxsTicketMapper.updateById(kxsTicket);
                        }
                }
            }


        }


        return R.ok();
    }



    @Override
    public R cancelOrder(KxsShopOrder param) {

        KxsShopOrder order = baseMapper.selectById(param.getId());
        if(order == null){
            return R.failed(ProductErrorTypeEnum.ORDER_EMPTY.getDescription());
        }
        if(!order.getStatus().equals(KxsShopEnum.ORDER_NO_PAY.getType())){
            return R.failed(ProductErrorTypeEnum.ORDER_NO_CANCEL.getDescription());
        }
        order.setStatus(KxsShopEnum.ORDER_CANCEL.getType());
        baseMapper.updateById(order);

        return R.ok();
    }

    @Override
    public R confirmOrder(KxsShopOrder param) {

        KxsShopOrder order = baseMapper.selectById(param.getId());
        if(order == null){
            return R.failed(ProductErrorTypeEnum.ORDER_EMPTY.getDescription());
        }
        if(!order.getStatus().equals(KxsShopEnum.ORDER_NO_TAKE.getType())){
            return R.failed(ProductErrorTypeEnum.ORDER_NO_CONFIRM.getDescription());
        }
        order.setStatus(KxsShopEnum.ORDER_CONFIRM.getType());
        baseMapper.updateById(order);

        return R.ok();
    }

    @Override
    public IPage<ShopOrderListVO> getByPage(Page<ShopOrderListVO> page, KxsShopOrder param) {

        Long userId = SecurityUtils.getUser().getId();
        param.setUserId(userId);
        //自定义分页
        long start = (page.getCurrent() - 1) * page.getSize();
        start = start < 0 ? 0L : start;

        Long count = baseMapper.selectCount(Wrappers.query(param));
        List<ShopOrderListVO> orderListVos = baseMapper.getByPage(start, page.getSize(), param);
        page.setRecords(orderListVos);
        page.setTotal(count);

        return page;
    }

    @Override
    public ShopOrderCountVO orderUnCount() {

        Long userId = SecurityUtils.getUser().getId();

        Long noPayCount = baseMapper.selectCount(Wrappers.<KxsShopOrder>lambdaQuery()
                .eq(KxsShopOrder::getUserId, userId)
                .eq(KxsShopOrder::getStatus, KxsShopEnum.ORDER_NO_PAY.getType()));
        Long noSendCount = baseMapper.selectCount(Wrappers.<KxsShopOrder>lambdaQuery()
                .eq(KxsShopOrder::getUserId, userId)
                .eq(KxsShopOrder::getStatus, KxsShopEnum.ORDER_NO_SEND.getType()));

        return ShopOrderCountVO.builder().needPayCount(noPayCount).needSendCount(noSendCount).build();
    }

    @Override
    public List<ShopOrderGoodsUserVO> getDateBetweenOrders(String startTime, String endTime) {

        return baseMapper.getDateBetweenOrders(startTime, endTime);

    }


    /**
     * 支付宝支付
     *
     * @param param   参数
     * @param subject 订单标题。
     * @return {@link R}
     */
    private R aliPay(KxsShopOrder param, String subject){

        try {
            PayRequest payReq = new PayRequest();
            payReq.setPayTypeEnum(PayPlatformEnum.ALIPAY);
            payReq.setOutTradeNo(param.getOrderSn());
            payReq.setSubject(subject);
            payReq.setTotalAmount(param.getPayPrice().doubleValue());
            //扩展参数
            payReq.setPassbackParams("shop_order");

            PayResponse payResponse = paymentFactory.getPayService(PayPlatformEnum.ALIPAY.getType()).appPay(payReq);

            return R.ok(payResponse);
        } catch (AlipayApiException e) {
            log.error("支付宝支付异常:{}", param.getOrderSn(), e);
            throw new GlobalCustomerException("支付宝参数异常");
        }
    }


}

