package com.fdkankan.ucenter.service.impl;

import com.amazonaws.services.codecommit.model.OrderEnum;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fdkankan.common.constant.TbStatus;
import com.fdkankan.common.exception.BusinessException;
import com.fdkankan.ucenter.common.PageInfo;
import com.fdkankan.common.util.FileUtils;
import com.fdkankan.common.util.NumberUtils;
import com.fdkankan.redis.util.RedisUtil;
import com.fdkankan.ucenter.common.RedisKeyUtil;
import com.fdkankan.ucenter.constant.*;
import com.fdkankan.ucenter.entity.*;
import com.fdkankan.ucenter.httpClient.param.PayGoods;
import com.fdkankan.ucenter.httpClient.service.PayService;
import com.fdkankan.ucenter.httpClient.vo.PayOrderVo;
import com.fdkankan.ucenter.mapper.IOrderMapper;
import com.fdkankan.ucenter.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fdkankan.ucenter.util.DateUserUtil;
import com.fdkankan.ucenter.vo.request.CartParam;
import com.fdkankan.ucenter.vo.request.DownNumParam;
import com.fdkankan.ucenter.vo.request.OrderParam;
import com.fdkankan.ucenter.vo.request.PlaceOrderParam;
import com.fdkankan.ucenter.vo.response.GoodsSkuVo;
import com.fdkankan.ucenter.vo.response.OrderVo;
import com.google.common.collect.Ordering;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author 
 * @since 2022-07-13
 */
@Service
public class OrderServiceImpl extends ServiceImpl<IOrderMapper, Order> implements IOrderService {

    @Autowired
    IUserService userService;
    @Autowired
    IOrderItemService orderItemService;
    @Autowired
    IInvoiceService invoiceService;
    @Autowired
    IIncrementOrderService incrementOrderService;
    @Autowired
    ICartService cartService;
    @Autowired
    IGoodsService goodsService;
    @Autowired
    IGoodsSkuService goodsSkuService;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    IDownloadOrderService downloadOrderService;
    @Autowired
    IIncrementTypeService incrementTypeService;
    @Autowired
    IUserIncrementService userIncrementService;
    @Autowired
    IOrderService orderService;
    @Autowired
    IIncrementAutoOrderService incrementAutoOrderService;
    @Autowired
    IProductOrderService productOrderService;

    @Override
    public PageInfo pageList(OrderParam param) {
        User user = userService.getByUserName(param.getUserName());
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getUserId,user.getId());
        wrapper.eq(Order::getPaymentStatus,"paid");
        wrapper.orderByDesc(Order::getOrderTime);
        Page<Order> page = this.page(new Page<>(param.getPageNum(), param.getPageSize()), wrapper);
        List<OrderVo> orderVos = new ArrayList<>();
        for (Order record : page.getRecords()) {
            OrderVo orderVo = new OrderVo();
            BeanUtils.copyProperties(record,orderVo);

            Invoice invoice = invoiceService.getByOrderId(record.getId());
            orderVo.setInvoice(invoice);

            List<OrderItem> itemList = orderItemService.getByOrderId(record.getId());
            orderVo.setOrderItems(itemList);
            orderVos.add(orderVo);
        }
        Page<OrderVo> pageVo = new Page<>(param.getPageNum(),param.getPageSize());
        pageVo.setRecords(orderVos);
        pageVo.setTotal(page.getTotal());
        return PageInfo.PageInfo(pageVo);
    }

    @Override
    public GoodsSkuVo getIncrementOrDownloadPrice(OrderParam param) {
        return incrementOrderService.getDownloadPrice(param);
    }

    @Override
    public void cancel(Long orderId) {
        LambdaUpdateWrapper<Order> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(Order::getOrderStatus, OrderStatus.invalid)
                .eq(Order::getId,orderId);
        this.update(wrapper);
    }

    @Override
    public void receipt(Long orderId) {
        LambdaUpdateWrapper<Order> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(Order::getOrderStatus, OrderStatus.completed)
                .set(Order::getShippingStatus, ShippingStatus.received)
                .eq(Order::getId,orderId);
        this.update(wrapper);
    }

   @Autowired
    PayService payService;

    @Override
    public Order placeOrder(PlaceOrderParam param) {
        List<Long> id = param.getGoods().parallelStream().map(CartParam::getId).collect(Collectors.toList());
        List<String> ids = new ArrayList<>();
        for (Long aLong : id) {
            ids.add(String.valueOf(aLong));
        }
        User user = userService.getByUserName(param.getUserName());
        cartService.deleteIds(ids);
        // 下单
        List<OrderItem> orderItemEntities = new ArrayList<>();
        OrderItem orderItemEntity = null;
        int goodsTotalCount = 0;
        BigDecimal goodsAmount = new BigDecimal(0);
        List<PayGoods> goodsInfoList = new ArrayList<>();
        for(CartParam requestCart : param.getGoods()){
            goodsTotalCount += requestCart.getGoodsCount();

            Goods responseGoods = goodsService.getById(requestCart.getGoodsId());
            if (responseGoods == null){
                continue;
            }
            GoodsSku sku = goodsSkuService.getBySku(requestCart.getSkuSn());
            if (sku == null){
                throw new BusinessException(500,LoginConstant.ERROR_MSG);
            }
            orderItemEntity = new OrderItem();
            orderItemEntity.setExpressNum(null);
            orderItemEntity.setGoodsPrice(param.getAbroad().intValue() == 0 ? sku.getPrice() : sku.getDollarPrice());
            orderItemEntity.setGoodsId(requestCart.getGoodsId());
            orderItemEntity.setShippingStatus(ShippingStatus.unshipped.name());
            orderItemEntity.setExpressName("顺丰速运");
            orderItemEntity.setGoodsCount(requestCart.getGoodsCount());
            orderItemEntity.setGoodsName(responseGoods.getName());
            orderItemEntity.setGoodsSn(responseGoods.getGoodsSn());
            orderItemEntity.setRecStatus("A");
            orderItemEntity.setCreateTime(DateUserUtil.getDate(new Date()));
            orderItemEntity.setUpdateTime(DateUserUtil.getDate(new Date()));
            if (StringUtils.isNotEmpty(requestCart.getSkuSn())){
                orderItemEntity.setSkuSn(requestCart.getSkuSn());
            }
            orderItemEntities.add(orderItemEntity);

            goodsAmount = goodsAmount.add(orderItemEntity.getGoodsPrice().multiply(new BigDecimal(orderItemEntity.getGoodsCount())));
            PayGoods payGoods = new PayGoods(orderItemEntity.getGoodsName(),responseGoods.getNameEn(),orderItemEntity.getGoodsCount(),3);
            goodsInfoList.add(payGoods);
        }

        PayOrderVo payOrderVo = payService.downOrder(goodsAmount, "partOrder",user.getUserName(),user.getNickName(),goodsInfoList,null);
        if(payOrderVo == null){
            throw new BusinessException(OrderConstant.FAILURE_CODE_8005,OrderConstant.FAILURE_MSG_8005);
        }
        Order orderEntity = new Order();
        orderEntity.setOrderSn(payOrderVo.getOrderSn());
        orderEntity.setOrderTime(DateUserUtil.getDate(new Date()));
        orderEntity.setOrderStatus(OrderStatus.unprocessed.name());
        orderEntity.setPaymentStatus(PaymentStatus.unpaid.name());
        orderEntity.setShippingStatus(ShippingStatus.unshipped.name());
        orderEntity.setPaymentTypeName(param.getPayType());
        orderEntity.setUserId(user.getId());
        orderEntity.setGoodsTotalCount(goodsTotalCount);
        orderEntity.setGoodsAmount(goodsAmount);
        orderEntity.setTotalAmount(goodsAmount);
        orderEntity.setPaidAmount(BigDecimal.ZERO);
        orderEntity.setExpressAmount(BigDecimal.ZERO);
        orderEntity.setDeliveryTypeName("快递运输");
        orderEntity.setRecStatus("A");
        orderEntity.setCreateTime(DateUserUtil.getDate(new Date()));
        orderEntity.setUpdateTime(DateUserUtil.getDate(new Date()));

        if (param.getReceiver() != null){
            orderEntity.setShipAddress(param.getReceiver().getShipAddress());
            orderEntity.setShipAreaPath(param.getReceiver().getShipAreaPath());
            orderEntity.setShipMobile(param.getReceiver().getShipMobile());
            orderEntity.setShipName(param.getReceiver().getShipName());
        }
        orderEntity.setAbroad(param.getAbroad());
        this.save(orderEntity);

        for (OrderItem entity : orderItemEntities){
            entity.setOrderId(orderEntity.getId());
        }
        orderItemService.saveBatch(orderItemEntities);

        if(param.getInvoice()!=null && StringUtils.isNotBlank(param.getInvoice().getInvoiceType())){
            param.setOrderId(orderEntity.getId());
            param.getInvoice().setAmount(orderEntity.getTotalAmount().toString());
            invoiceService.saveByOrder(user.getId(),param);
        }
        return orderEntity;
    }

    @Override
    public boolean queryOrderStatus(OrderParam param) throws Exception {
        String orderSn = param.getOrderSn();
        if(StringUtils.isBlank(orderSn)){
            return false;
        }
        Order order = orderService.getByOrderSn(orderSn);
        //付款状态（未付款unpaid、已付款paid、已取消cancel, 部分支付partPayment, 部分退款partRefund, 全额退款refunded）
        if(order != null && order.getPaymentStatus().equals("paid")){
            return true;
        }
        DownloadOrder downloadOrder = downloadOrderService.getByOrderSn(orderSn);
        if(downloadOrder != null && downloadOrder.getPayStatus() == 1){
            return true;
        }
        IncrementOrder incrementOrder = incrementOrderService.getByOrderSn(orderSn);
        if(incrementOrder != null && incrementOrder.getPayStatus() == 1){
            return true;
        }
        IncrementAutoOrder autoOrder = incrementAutoOrderService.getByOrderSn(orderSn);
        if(autoOrder != null && StringUtils.isNotBlank(autoOrder.getSubscriptionId())){
            return true;
        }
        ProductOrder productOrder = productOrderService.getByOrderSn(orderSn);
        if(productOrder != null && productOrder.getPayStatus() == 1){
            return true;
        }
        return false;
    }

    @Override
    public Order getByOrderSn(String orderSn) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getOrderSn,orderSn);
        return this.getOne(wrapper);
    }

    @Override
    public Order getByOrderSnNoPay(String orderSn) {
        LambdaQueryWrapper<Order> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Order::getOrderSn,orderSn);
        wrapper.ne(Order::getPaymentStatus, PaymentStatus.paid.name());
        return this.getOne(wrapper);    }

    @Override
    public DownloadOrder downloadOrder(DownNumParam param) {
        //支付美金，只能paypal支付
        if(param.getAbroad() == 1 && param.getPayType() != 2){
            throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
        }
        IncrementType incrementType = incrementTypeService.getById(param.getIncrementType());
        if(incrementType == null){
          throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
        }
//        GoodsSku goodsSku = goodsSkuService.getBySku(param.getSkuSn());
//        if(goodsSku == null){
//            throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
//        }
        User user = userService.getByUserName(param.getUserName());
        if(user == null){
            throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
        }

        return downloadOrderService.insertDownloadOrder(user,param,incrementType.getDownloadPrice());
    }

    @Override
    public IncrementOrder incrementOrder(DownNumParam param) {
        //支付美金，只能paypal支付
        if(param.getAbroad() == 1 && param.getPayType() != 2){
            throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
        }
        User user = userService.getByUserName(param.getUserName());
        if(user == null){
            throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
        }
        if(param.getIncrementId() != null){
            UserIncrement userIncrement = userIncrementService.getById(param.getIncrementId());
            if(userIncrement == null){
                throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);

            }
            IncrementType incrementType = incrementTypeService.getById(userIncrement.getIncrementTypeId());
            if(incrementType == null){
                throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
            }
            return incrementOrderService.insertIncrementOrder(user, param,incrementType);
        }
        IncrementType incrementType = incrementTypeService.getById(param.getIncrementTypeId());
        if(incrementType == null){
            throw new BusinessException(OrderConstant.FAILURE_CODE_8004, OrderConstant.FAILURE_MSG_8004);
        }
        return incrementOrderService.insertIncrementOrder(user, param,incrementType);
    }

    @Override
    public boolean paySuccessEntityOrder(String orderSn, String tradeNo, int paymentTypeName) {
        LambdaUpdateWrapper<Order> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(Order::getPaymentTypeName,paymentTypeName)
                .set(Order::getTradeNum,tradeNo)
                .set(Order::getPaymentStatus, PaymentStatus.paid.name())
                .eq(Order::getOrderSn,orderSn);
        return this.update(updateWrapper);
    }

    @Override
    public OrderVo getOrderDetail(Long orderId) {
        Order order = this.getById(orderId);
        OrderVo responseOrder = new OrderVo();
        if(order == null ){
            return responseOrder;
        }
        BeanUtils.copyProperties(order,responseOrder);

        List<OrderItem> responseOrderItems =orderItemService.getByOrderId(orderId);
        responseOrder.setOrderItems(responseOrderItems);

        Invoice invoice = invoiceService.getByOrderId(orderId);
        if(invoice != null){
            responseOrder.setInvoice(invoice);
        }
        return responseOrder;
    }

    @Override
    public void autoUpdateOrderStatus() {
        this.getBaseMapper().autoUpdateOrderStatus();
    }
}
