/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.api.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.*;
import com.yami.shop.bean.app.param.*;
import com.yami.shop.bean.event.ConfirmOrderEvent;
import com.yami.shop.bean.event.PlatformConfirmOrderEvent;
import com.yami.shop.bean.event.ScoreConfirmOrderEvent;
import com.yami.shop.bean.event.SubmitSeckillOrderEvent;
import com.yami.shop.bean.model.*;
import com.yami.shop.common.exception.GlobalException;
import com.yami.shop.common.util.Arith;
import com.yami.shop.dao.PointsRecordMapper;
import com.yami.shop.dao.ShopSkuMapper;
import com.yami.shop.security.api.util.SecurityUtils;
import com.yami.shop.service.*;
import com.yami.shop.service.hb.IHBOrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/p/order")
@Api(tags = "订单接口")
public class OrderController {

    @Autowired
    private OrderService orderService;
    @Autowired
    private MapperFacade mapperFacade;
    @Autowired
    private SkuService skuService;
    @Autowired
    private ProductService productService;
    @Autowired
    private UserAddrService userAddrService;
    @Autowired
    private BasketService basketService;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private UserAddrOrderService userAddrOrderService;
    @Autowired
    private IQnhService qnhService;
    @Autowired
    private PointsRecordMapper pointsRecordMapper;

    @Autowired
    private IHBOrderService hbOrderService;
    @Autowired
    private ShopSkuMapper shopSkuMapper;

    /**
     * 生成订单
     */
    @PostMapping("/confirm")
    @ApiOperation(value = "结算，生成订单信息", notes = "传入下单所需要的参数进行下单")
    public ResponseEntity<ShopCartOrderMergerDto> confirm(@Valid @RequestBody OrderParam orderParam) {
        if (orderParam.getShopId() == null) {
//            orderParam.setShopId(1L);
            throw new GlobalException("请选择店铺！");
        }
        String userId = SecurityUtils.getUser().getUserId();

        if (orderParam.getOrderItem() == null) {
            orderParam.getBasketIds().forEach(basketId -> {
                Basket byId = basketService.getById(basketId);
                Sku byIdss = skuService.getById(byId);
                ShopSku shopSku = shopSkuMapper.selectByShopAndSku(byIdss.getSkuId(), orderParam.getShopId());
                if (shopSku.getShopSkuStocks() == null || shopSku.getShopSkuStocks() == 0) {
                    throw new GlobalException("当前选择的商品[" + byIdss.getSkuName() + "]库存为空！请重新选择商品！");
                }
                if (shopSku.getShopSkuStocks() < byId.getBasketCount()) {
                    throw new GlobalException("当前选择的商品[" + byIdss.getSkuName() + "]库存不足！");
                }

            });
        } else {
            ShopSku shopSku = shopSkuMapper.selectByShopAndSku(orderParam.getOrderItem().getSkuId(), orderParam.getShopId());
            if (shopSku.getShopSkuStocks() == null || shopSku.getShopSkuStocks() == 0) {
                throw new GlobalException("商品:[" + shopSku.getSkuName() + "]库存为空！请重新选择商品！");
            }
            if (shopSku.getShopSkuStocks() < orderParam.getOrderItem().getProdCount()) {
                throw new GlobalException("商品:[" + shopSku.getSkuName() + "]库存不足！");
            }
        }

        // 订单的地址信息
        UserAddr userAddr = userAddrService.getUserAddrByUserId(orderParam.getAddrId(), userId);
        UserAddrDto userAddrDto = mapperFacade.map(userAddr, UserAddrDto.class);
        // 组装获取用户提交的购物车商品项
        OrderItemParam orderItem = orderParam.getOrderItem();
        if (null != orderItem) {
            orderItem.setChannelId(orderParam.getChannelId());
        }

        System.out.println("orderParam.getBasketIds()" + orderParam.getBasketIds());
        System.out.println("orderItem" + orderItem);
        System.out.println("userId" + userId);
        List<ShopCartItemDto> shopCartItems = basketService.getShopCartItemsByOrderItems(orderParam.getBasketIds(), orderItem, userId, orderParam.getChannelId());
        if (CollectionUtil.isEmpty(shopCartItems)) {
            throw new GlobalException("请选择您需要的商品加入购物车");
        }
        // 根据店铺组装购车中的商品信息，返回每个店铺中的购物车商品信息
        List<ShopCartDto> shopCarts = basketService.getShopCarts(shopCartItems, 0L);

        Long point = pointsRecordMapper.statisticsPoint(userId, orderParam.getChannelId());
        double v = 0.0;
        // 将要返回给前端的完整的订单信息
        ShopCartOrderMergerDto shopCartOrderMergerDto = new ShopCartOrderMergerDto();
        shopCartOrderMergerDto.setUserAddr(userAddrDto);
        shopCartOrderMergerDto.setIsScorePay(orderParam.getIsScorePay());
        if (null != point) {
            v = ((double) point / 100);
            //总的可用积分
//        shopCartOrderMergerDto.setTotalAvailableScore(point);
        }

        // 所有店铺的订单信息
        List<ShopCartOrderDto> shopCartOrders = new ArrayList<>();

        double actualTotal = 0.0;
        double total = 0.0;
        int totalCount = 0;
        double allOrderReduce = 0.0;
        double totalTransfee = 0.0;
        double weight = 0.0;

        // 所有店铺所有的商品item
        List<ShopCartItemDto> allCartItem = new ArrayList<>();

//        List<CouponOrderDto> coupons = new ArrayList<>();
        for (ShopCartDto shopCart : shopCarts) {
            // 每个店铺的订单信息
            ShopCartOrderDto shopCartOrder = new ShopCartOrderDto();
            shopCartOrder.setShopId(shopCart.getShopId());
            shopCartOrder.setShopName(shopCart.getShopName());

            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCart.getShopCartItemDiscounts();
            // 店铺中的所有商品项信息
            List<ShopCartItemDto> shopAllShopCartItems = new ArrayList<>();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                List<ShopCartItemDto> discountShopCartItems = shopCartItemDiscount.getShopCartItems();
                shopAllShopCartItems.addAll(discountShopCartItems);
            }
            shopCartOrder.setShopCartItemDiscounts(shopCartItemDiscounts);
            allCartItem.addAll(shopAllShopCartItems);

            applicationContext.publishEvent(new ConfirmOrderEvent(shopCartOrder, orderParam, shopAllShopCartItems));

            total = Arith.add(total, shopCartOrder.getTotal());
            totalCount = totalCount + shopCartOrder.getTotalCount();
            allOrderReduce = Arith.add(allOrderReduce, shopCartOrder.getShopReduce());
            totalTransfee = Arith.add(totalTransfee, shopCartOrder.getTransfee());
            weight = Arith.add(weight, shopCartOrder.getTotalWeight());
            shopCartOrders.add(shopCartOrder);
        }
        shopCartOrderMergerDto.setDvyType(orderParam.getDvyType());

        //根据价格进行店铺、满减、商品项的价格升序操作
        for (int n = 0; n < shopCartOrders.size(); n++) {
            shopCartOrders = shopCartOrders.stream().sorted(Comparator.comparing(ShopCartOrderDto::getActualTotal)).collect(Collectors.toList());
            ShopCartOrderDto shopCartOrderDto = shopCartOrders.get(n);

            List<ShopCartItemDiscountDto> shopCartItemDiscounts = shopCartOrderDto.getShopCartItemDiscounts();
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartItemDiscounts) {
                List<ShopCartItemDto> sortShopCartItems = shopCartItemDiscount.getShopCartItems();
                sortShopCartItems = sortShopCartItems.stream().sorted(Comparator.comparing(ProductItemDto::getActualTotal)).collect(Collectors.toList());
                shopCartItemDiscount.setShopCartItems(sortShopCartItems);
                double totalAmount = shopCartItemDiscount.getShopCartItems().stream().mapToDouble(ProductItemDto::getActualTotal).sum();
                shopCartItemDiscount.setTotalAmount(totalAmount);
            }
            // 如果是折扣特别小的情况下，导致实际金额为0是，改变最小支付金额为0.01元,并且优惠金额减去0.01。
            if (shopCartOrderDto.getActualTotal() <= 0) {
                shopCartOrderDto.setActualTotal(0.01);
                shopCartOrderDto.setShopReduce(Arith.sub(shopCartOrderDto.getShopReduce(), 0.01));
                List<ShopCartItemDto> sortItems = shopCartItemDiscounts.get(shopCartItemDiscounts.size() - 1).getShopCartItems();
                ShopCartItemDto shopCartItemDto = sortItems.get(sortItems.size() - 1);
                shopCartItemDto.setActualTotal(0.01);
                shopCartItemDto.setShareReduce(Arith.sub(shopCartItemDto.getShareReduce(), 0.01));
            }
            shopCartItemDiscounts = shopCartItemDiscounts.stream().sorted(Comparator.comparing(ShopCartItemDiscountDto::getTotalAmount)).collect(Collectors.toList());
            shopCartOrders.get(n).setShopCartItemDiscounts(shopCartItemDiscounts);
            actualTotal = Arith.add(actualTotal, shopCartOrderDto.getActualTotal());
        }
        //v
        shopCartOrderMergerDto.setActualTotal(Arith.sub(actualTotal, v) < 0 ? 0 : Arith.sub(actualTotal, v));
        shopCartOrderMergerDto.setTotalUsableScore(Arith.sub(actualTotal, v) < 0 ? actualTotal : v);//总共消耗的积分
//        shopCartOrderMergerDto.setTotalAvailableScore(point);

        shopCartOrderMergerDto.setTotalAvailableScore((long) Arith.mul(shopCartOrderMergerDto.getTotalUsableScore(), 100));//总共消耗的积分
        shopCartOrderMergerDto.setTotal(total);
        shopCartOrderMergerDto.setTotalCount(totalCount);
        shopCartOrderMergerDto.setOrderReduce(allOrderReduce);
        shopCartOrderMergerDto.setTotalTransfee(totalTransfee);
        shopCartOrderMergerDto.setUuid(orderParam.getUuid());
        shopCartOrderMergerDto.setShopCartOrders(shopCartOrders);
        shopCartOrderMergerDto.setWeight(weight);

        applicationContext.publishEvent(new PlatformConfirmOrderEvent(shopCartOrderMergerDto, orderParam, allCartItem));

        // ============  通过订单项的金额，计算出订单总金额  ==============

        //所有订单实际金额
        actualTotal = 0.00;
        //所有订单优惠金额
        allOrderReduce = 0.00;
        totalTransfee = 0.00;
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            //订单实际金额
            double orderActualTotal = 0.00;
            //商家优惠金额
            double orderReduceAmount = 0.00;
            //商家优惠金额
            double orderPlatformAmount = 0.00;

            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartOrder.getShopCartItemDiscounts()) {
                for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
                    shopCartItem.setPlatformShareReduce(Arith.round(shopCartItem.getPlatformShareReduce(), 2));
                    shopCartItem.setShareReduce(Arith.add(Arith.round(shopCartItem.getShareReduce(), 2), shopCartItem.getPlatformShareReduce()));
                    shopCartItem.setActualTotal(Arith.sub(shopCartItem.getProductTotalAmount(), shopCartItem.getShareReduce()));
                    orderActualTotal = Arith.add(orderActualTotal, shopCartItem.getActualTotal());
                    orderReduceAmount = Arith.add(orderReduceAmount, shopCartItem.getShareReduce());
                    orderPlatformAmount = Arith.add(orderPlatformAmount, shopCartItem.getPlatformShareReduce());
                }
            }
            shopCartOrder.setActualTotal(Arith.add(orderActualTotal, shopCartOrder.getTransfee()));
//            shopCartOrder.setActualTotal(100.0);
            //放入优惠金额
            shopCartOrder.setShopReduce(Arith.add(orderReduceAmount, shopCartOrder.getFreeTransfee()));
            //放入平台优惠金额,如果用户等级免自营店运费也要放进去
            shopCartOrder.setPlatformAmount(Arith.add(orderPlatformAmount, shopCartOrder.getFreeTransfee()));

            actualTotal = Arith.add(actualTotal, shopCartOrder.getActualTotal());
            allOrderReduce = Arith.add(allOrderReduce, shopCartOrder.getShopReduce());
            totalTransfee = Arith.add(totalTransfee, shopCartOrder.getTransfee());
        }
        shopCartOrderMergerDto.setActualTotal(Arith.sub(actualTotal, v) < 0 ? 0 : Arith.sub(actualTotal, v));
        shopCartOrderMergerDto.setTotalUsableScore(Arith.sub(actualTotal, v) < 0 ? actualTotal : v);//总共消耗的积分
        shopCartOrderMergerDto.setTotalAvailableScore((long) Arith.mul(shopCartOrderMergerDto.getTotalUsableScore(), 100));
        shopCartOrderMergerDto.setTotalTransfee(totalTransfee);
        shopCartOrderMergerDto.setOrderReduce(allOrderReduce);

        applicationContext.publishEvent(new ScoreConfirmOrderEvent(shopCartOrderMergerDto, orderParam, allCartItem));
        orderService.putConfirmOrderCache(userId + orderParam.getUuid(), shopCartOrderMergerDto);

        return ResponseEntity.ok(shopCartOrderMergerDto);
    }

    /**
     * 购物车/立即购买  提交订单,根据店铺拆单
     */
    @PostMapping("/submit")
    @ApiOperation(value = "提交订单，返回支付流水号", notes = "根据传入的参数判断是否为购物车提交订单，同时对购物车进行删除，用户开始进行支付")
    public ResponseEntity<OrderNumbersDto> submitOrders(@Valid @RequestBody SubmitOrderParam submitOrderParam) {
        //扣减积分,先获取当前用户的所以积分，计算扣除之后是否还需要微信支付
        String userId = SecurityUtils.getUser().getUserId();
        ShopCartOrderMergerDto mergerOrder = orderService.getConfirmOrderCache(userId + submitOrderParam.getUuid());

        if (mergerOrder == null) {
            throw new GlobalException("订单已过期，请重新下单");
        }
        // 校验商品是否删除


        List<OrderShopParam> orderShopParams = submitOrderParam.getOrderShopParam();
        List<ShopCartOrderDto> shopCartOrders = mergerOrder.getShopCartOrders();
        // 设置备注
        if (CollectionUtil.isNotEmpty(orderShopParams)) {
            for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
                for (OrderShopParam orderShopParam : orderShopParams) {
                    if (Objects.equals(shopCartOrder.getShopId(), orderShopParam.getShopId())) {
                        shopCartOrder.setRemarks(orderShopParam.getRemarks());
                    }
                }
            }
        }
        mergerOrder.setChannelId(submitOrderParam.getChannelId());
        List<Order> orders = orderService.submit(userId, mergerOrder);

        StringBuilder orderNumbers = new StringBuilder();
        for (Order order : orders) {
            orderNumbers.append(order.getOrderNumber()).append(",");
        }
        orderNumbers.deleteCharAt(orderNumbers.length() - 1);

        boolean isShopCartOrder = false;
        // 移除缓存
        for (ShopCartOrderDto shopCartOrder : shopCartOrders) {
            for (ShopCartItemDiscountDto shopCartItemDiscount : shopCartOrder.getShopCartItemDiscounts()) {
                for (ShopCartItemDto shopCartItem : shopCartItemDiscount.getShopCartItems()) {
                    Long basketId = shopCartItem.getBasketId();
                    if (basketId != null && basketId != 0) {
                        isShopCartOrder = true;
                    }
                    skuService.removeSkuCacheBySkuId(shopCartItem.getSkuId(), shopCartItem.getProdId());
                    productService.removeProductCacheByProdId(shopCartItem.getProdId());
                }
            }
        }
        // 购物车提交订单时(即有购物车ID时)
        if (isShopCartOrder) {
            basketService.removeShopCartItemsCacheByUserId(userId);
        }
        orderService.removeConfirmOrderCache(userId + submitOrderParam.getUuid());
        for (Order order : orders) {
            if (!order.getNextPay()) {
                //不拆单和已拆单推到海博
//                if (order.getSplitStatus() == 1 || order.getOrderLevel() == 1) {
                    //推送海博订单
                    hbOrderService.createOrderAsync(order.getOrderNumber());
//                }
            }
        }

        return ResponseEntity.ok(new OrderNumbersDto(orderNumbers.toString(), mergerOrder.getNextPay()));
    }

    @GetMapping("/getOrderPayInfoByOrderNumber")
    @ApiOperation(value = "获取订单支付信息", notes = "获取订单支付的商品/地址信息")
    @ApiImplicitParam(name = "orderNumbers", value = "订单流水号", required = true, dataType = "String")
    public ResponseEntity<OrderPayInfoParam> getOrderPayInfoByOrderNumber(@RequestParam("orderNumbers") String orderNumbers) {
        List<String> orderNumberList = Arrays.asList(orderNumbers.split(","));
        //获取订单信息
        List<Order> orderList = orderService.getOrderPayInfoByOrderNumber(orderNumberList);
        List<String> prodNameList = Lists.newArrayList();
        Long addrOrderId = null;
        Date endTime = null;
        int totalScore = 0;
        double totalFee = 0.0;
        //获取商品名集合
        for (Order order : orderList) {
            for (OrderItem orderItem : order.getOrderItems()) {
                prodNameList.add(orderItem.getProdName());
                totalScore += orderItem.getUseScore() != null ? orderItem.getUseScore() : 0;
            }
            //第一次循环，获取订单地址id，订单过期时间
            if (Objects.isNull(addrOrderId)) {
                addrOrderId = order.getAddrOrderId();
                if (Objects.equals(2, order.getOrderType())) {
                    // 获取秒杀订单的取消订单时间
                    Integer maxCancelTime = 0;
                    SubmitSeckillOrderEvent event = new SubmitSeckillOrderEvent(order, maxCancelTime);
                    applicationContext.publishEvent(event);
                    maxCancelTime = event.getMaxCancelTime();
                    if (maxCancelTime <= 0) {
                        maxCancelTime = 30;
                    }
                    endTime = DateUtil.offsetMinute(order.getCreateTime(), maxCancelTime);
                } else {
                    endTime = DateUtil.offsetMinute(order.getCreateTime(), 30);
                }
            }
            totalFee = Arith.add(totalFee, order.getActualTotal());
        }
        //写入商品名、收货地址/电话
        UserAddrOrder userAddrOrder = userAddrOrderService.getById(addrOrderId);
        String addr = userAddrOrder.getProvince() + userAddrOrder.getCity() + userAddrOrder.getArea() + userAddrOrder.getAddr();
        OrderPayInfoParam orderPayInfoParam = new OrderPayInfoParam();
        orderPayInfoParam.setProdNameList(prodNameList);
        orderPayInfoParam.setReceiver(userAddrOrder.getReceiver());
        orderPayInfoParam.setUserAddr(addr);
        orderPayInfoParam.setMobile(userAddrOrder.getMobile());
        orderPayInfoParam.setEndTime(endTime);
        orderPayInfoParam.setTotalFee(totalFee);
        orderPayInfoParam.setTotalScore(totalScore);
        return ResponseEntity.ok(orderPayInfoParam);
    }
}
