package com.gxwebsoft.apps.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.gxwebsoft.apps.entity.BcCart;
import com.gxwebsoft.apps.result.CartResult;
import com.gxwebsoft.common.core.exception.BusinessException;
import com.gxwebsoft.common.core.utils.JSONUtil;
import com.gxwebsoft.common.core.web.ApiResult;
import com.gxwebsoft.common.core.web.BaseController;
import com.gxwebsoft.shop.entity.Goods;
import com.gxwebsoft.shop.entity.Order;
import com.gxwebsoft.shop.entity.OrderGoods;
import com.gxwebsoft.shop.param.CartParam;
import com.gxwebsoft.shop.service.GoodsService;
import com.gxwebsoft.shop.service.OrderGoodsService;
import com.gxwebsoft.shop.service.OrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.gxwebsoft.common.core.constants.OrderConstants.PAY_STATUS_SUCCESS;

/**
 * 批量报餐
 *
 * @author 科技小王子
 * @since 2022-11-25 19:04:43
 */
@Api(tags = "购物车记录表管理")
@RestController
@RequestMapping("/api/apps/bc-cart")
public class BcCartController extends BaseController {
  @Resource
  private GoodsService goodsService;
  @Resource
  private StringRedisTemplate stringRedisTemplate;
  @Resource
  private OrderService orderService;
  @Resource
  private OrderGoodsService orderGoodsService;

  @ApiOperation("添加购物车")
  @PostMapping("/addCart")
  public ApiResult<?> addCart(@RequestBody BcCart vo) {
    // 1. key = cache10048:cart651:2023-05-04
    String key = "cache" + getTenantId() + ":cart" + getLoginUserId() + ":" + vo.getDeliveryTime();
    // 2. 准备数据
    final Goods goods = goodsService.getById(vo.getGoodsId());
    vo.setImage(goods.getImage());
    vo.setGoodsName(goods.getGoodsName());
    vo.setComments(goods.getComments());
    vo.setCategoryId(goods.getCategoryId());
    vo.setGear(goods.getGear());
    vo.setUserId(getLoginUserId());
    // 2. 保存到购物车
    stringRedisTemplate.opsForHash().put(key, vo.getGoodsId().toString(), JSONObject.toJSONString(vo));
    //设置过期时间600秒
    System.out.println("设置过期时间600秒 = " + key);
    stringRedisTemplate.opsForHash().getOperations().expire(key,60*60*3, TimeUnit.SECONDS);
    // 3. 查询购物车并返回
    final List<BcCart> list = getCart(key);
    final ArrayList<CartResult> cartAll = getCartAll();
    return success("添加成功", cartAll);
  }

  @ApiOperation("查看购物车")
  @PostMapping("/showCart")
  public ApiResult<?> showCart() {
//    System.out.println("vo = " + vo);

    // 按预定日期查询
//    if (vo.getDeliveryTime() != null) {
//      // key = cache10048:cart651:2023-05-04
//      String key = "cache" + getTenantId() + ":cart" + getLoginUserId() + ":" + vo.getDeliveryTime();
//      final List<BcCart> list = getCart(key);
//      return success("获取成功", list);
//    }
    // 查询全部购物车数据
    return success("获取成功", getCartAll());
  }

  @ApiOperation("从购物车创建订单")
  @PostMapping("/createOrder")
  @Transactional(rollbackFor = {Exception.class})
  public ApiResult<?> createOrder(@RequestBody CartParam param) {
    // 1.判断是否代报餐
    Integer userId = 0;
    if (param.getAgentUserId() != null) {
      userId = param.getAgentUserId();
    } else {
      userId = getLoginUserId();
    }
    // 2.从缓存读取用户的购物车数据
    final ArrayList<CartResult> cartAll = getCartAll();
    if (cartAll.size() == 0) {
      throw new BusinessException("订单不存在");
    }
    // 3.批量创建订单
    Integer finalUserId = userId;
    final ArrayList<Object> orderIds = new ArrayList<>();
    cartAll.forEach(d -> {
      // 过滤空单
      if (!d.getTotalNum().equals(0)) {
        System.out.println("批量创建订单d = " + d);
        Order order = new Order();
        // 查询今日订单是否存在
        final Order one = orderService.getOne(new LambdaQueryWrapper<Order>()
          .eq(Order::getUserId, finalUserId)
          .eq(Order::getPayStatus,PAY_STATUS_SUCCESS)
          .eq(Order::getDeliveryTime, Date.valueOf(d.getDeliveryTime())));
        if(one == null){
          order.setOrderNo(String.valueOf(IdUtil.getSnowflakeNextId()));
          order.setTotalPrice(d.getTotalPrice());
          order.setOrderPrice(d.getTotalPrice());
          order.setPayPrice(d.getTotalPrice());
          order.setDeliveryTime(Date.valueOf(d.getDeliveryTime()));
          order.setExpirationTime(DateUtil.nextMonth());
          order.setIsTemporary(param.getIsTemporary());
          order.setUserId(finalUserId);
          order.setWeek(DateUtil.dayOfWeek(order.getDeliveryTime()) - 1);
          orderService.save(order);
        }else {
          order.setOrderId(one.getOrderId());
        }
        orderIds.add(order.getOrderId());

        // 添加订单商品
        final List<BcCart> items = d.getItems();
        final ArrayList<OrderGoods> orderGoods = new ArrayList<>();
        items.forEach(g -> {
          if(!g.getTotalNum().equals(0)){
            final OrderGoods og = new OrderGoods();
            og.setOrderId(order.getOrderId());
            og.setGoodsId(g.getGoodsId());
            og.setGoodsName(g.getGoodsName());
            og.setImageUrl(g.getImage());
            og.setTotalNum(g.getTotalNum());
            og.setCategoryId(g.getCategoryId());
            og.setGoodsPrice(g.getGoodsPrice());
            og.setComments(g.getComments());
            og.setGear(g.getGear());
            og.setGoodsId(g.getGoodsId());
            og.setTemporary(param.getIsTemporary());
            og.setUserId(finalUserId);
//          og.setDeliveryTime(order.getDeliveryTime());
            orderGoods.add(og);
          }
        });
        orderGoodsService.saveBatch(orderGoods);
      }
    });
    // 4.清空购物车
    removeCart();
    return success("创建成功",orderIds);
  }

  @ApiOperation("清空购物车")
  @GetMapping("/clearCart")
  public ApiResult<?> clearCart() {
    removeCart();
    return success("清空成功");
  }

  /**
   * 清空购物车
   */
  private void removeCart() {
    String key = "cache" + getTenantId() + ":cart" + getLoginUserId() + ":";
    final Set<String> keys = stringRedisTemplate.keys(key + "*");
    System.out.println("清空购物车keys = " + keys);
    assert keys != null;
    stringRedisTemplate.delete(keys);
  }

  /**
   * 获取购物车数据(按预定日期)
   */
  private List<BcCart> getCart(String key) {
    // 获取购物车数据
    List<Object> values = stringRedisTemplate.opsForHash().values(key);
    return values.stream().map(item -> JSONUtil.parseObject(JSONUtil.toJSONString(item), BcCart.class)).collect(Collectors.toList());
  }

  /**
   * 查询全部购物车数据
   */
  private ArrayList<CartResult> getCartAll() {
    String key = "cache" + getTenantId() + ":cart" + getLoginUserId();
    Set<String> keys = stringRedisTemplate.keys(key + "*");
//    System.out.println("keys = " + keys);
    assert keys != null;
    final ArrayList<CartResult> list = new ArrayList<>();
    keys.forEach(d -> {
      final List<Object> values = stringRedisTemplate.opsForHash().values(d);
      final CartResult cartResult = new CartResult();
      final ArrayList<BcCart> dataList = new ArrayList<>();

      values.forEach(item -> {
        BcCart bcCart = JSONUtil.parseObject(item.toString(), BcCart.class);
        assert bcCart != null;
//        System.out.println("cartResult = " + cartResult.getTotalPrice());
        if (cartResult.getTotalNum() == null) {
          cartResult.setTotalNum(0);
        }
        if (cartResult.getTotalPrice() == null) {
          cartResult.setTotalPrice(new BigDecimal(0));
        }
        cartResult.setTotalNum(cartResult.getTotalNum() + bcCart.getTotalNum());
        cartResult.setDeliveryTime(bcCart.getDeliveryTime());
        cartResult.setTotalPrice(cartResult.getTotalPrice().add(bcCart.getGoodsPrice().multiply(BigDecimal.valueOf(bcCart.getTotalNum()))));
        dataList.add(bcCart);
      });
      cartResult.setItems(dataList);
      list.add(cartResult);
    });
    return list;
  }

}
