package com.qs.mp.web.controller.api.user;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.NumberUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.mp.admin.domain.Goods;
import com.qs.mp.admin.domain.GoodsSku;
import com.qs.mp.admin.domain.vo.ShippingTemplateCalculateVO;
import com.qs.mp.admin.service.IGoodsService;
import com.qs.mp.admin.service.IGoodsSkuService;
import com.qs.mp.channel.domain.ChannelOrder;
import com.qs.mp.channel.domain.param.OrderPayParam;
import com.qs.mp.common.core.domain.AjaxResult;
import com.qs.mp.common.core.page.TableDataInfo;
import com.qs.mp.common.core.redis.RedisCache;
import com.qs.mp.common.domain.ShippingTemplate;
import com.qs.mp.common.domain.ShippingTemplateRule;
import com.qs.mp.common.enums.*;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.service.IShippingTemplateRuleService;
import com.qs.mp.common.service.IShippingTemplateService;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.framework.redis.RedisKey;
import com.qs.mp.pay.service.IWalletService;
import com.qs.mp.system.domain.SysUser;
import com.qs.mp.system.service.ISysUserService;
import com.qs.mp.user.domain.*;
import com.qs.mp.user.domain.param.DeliverOrderParam;
import com.qs.mp.user.domain.param.UserDeliverOrderCancelParam;
import com.qs.mp.user.domain.vo.DeliverOrderSettleVO;
import com.qs.mp.user.domain.vo.DeliverOrderVO;
import com.qs.mp.user.service.IUserAddrService;
import com.qs.mp.user.service.IUserDeliverOrderItemService;
import com.qs.mp.user.service.IUserDeliverOrderService;
import com.qs.mp.user.service.IUserPrizeStorageService;
import com.qs.mp.utils.SecurityUtils;
import com.qs.mp.web.controller.common.BaseApiController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import javax.validation.Valid;

import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.AllArgsConstructor;
import ma.glasnost.orika.MapperFacade;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;


@RestController
@RequestMapping("/api/v1/mp/user/deliver")
@Api(tags = "用户端奖品提货接口")
public class UserDeliverOrderController extends BaseApiController {

  @Autowired
  private IUserPrizeStorageService userPrizeStorageService;

  @Autowired
  private IUserAddrService userAddrService;

  @Autowired
  private IUserDeliverOrderService userDeliverOrderService;

  @Autowired
  private IUserDeliverOrderItemService userDeliverOrderItemService;

  @Autowired
  private IWalletService walletService;

  @Autowired
  private MapperFacade mapperFacade;

  @Autowired
  private ISysUserService sysUserService;

  @Autowired
  private RedisCache redisCache;

  @Autowired
  private IShippingTemplateRuleService shippingTemplateRuleService;

  @Autowired
  private IShippingTemplateService shippingTemplateService;

  @Autowired
  private IGoodsService goodsService;

  @Autowired
  private IGoodsSkuService goodsSkuService;

  @Value("${shipping.user}")
  public Long shippingTemplateId;

  /**
   * 订单列表
   */
  @PostMapping("/order/list")
  @ApiOperation(value = "订单列表" , notes = "获取所有订单信息")
  @ApiResponses(
          @ApiResponse(code = 200, message = "success", response = DeliverOrderVO.class)
  )
  public TableDataInfo list(@RequestBody JSONObject param) {
    Long userId = SecurityUtils.getLoginUser().getUserId();
    String status = param.getString("status");
    List<Integer> statusList = new ArrayList<>();
    if (StringUtils.isNotBlank(status)) {
      String[] arr = status.split(",");
      for (int i = 0; i < arr.length; i++) {
        statusList.add(Integer.valueOf(arr[i]));
      }
    }
    startPage();
    List<UserDeliverOrder> deliverOrders = userDeliverOrderService.list(
        new LambdaQueryWrapper<UserDeliverOrder>().eq(UserDeliverOrder::getUserId, userId)
            .in(!CollectionUtils.isEmpty(statusList), UserDeliverOrder::getStatus, statusList)
            .orderByDesc(UserDeliverOrder::getCreatedTime));
    List<DeliverOrderVO> deliverOrderVOList = mapperFacade.mapAsList(deliverOrders, DeliverOrderVO.class);
    for (DeliverOrderVO deliverOrderVO : deliverOrderVOList) {
      deliverOrderVO.setItems(userDeliverOrderItemService.selectUserDeliverOrderItemVOList(deliverOrderVO.getOrderId()));
    }
    TableDataInfo rspData = getDataTable(deliverOrders);
    rspData.setRows(deliverOrderVOList);
    return rspData;
  }

  /**
   * 订单详情
   */
  @PostMapping("/order/detail")
  @ApiOperation(value = "订单详情" , notes = "在订单列表页面查看详情")
  public AjaxResult query(@RequestBody UserDeliverOrder order) {
    Long userId = SecurityUtils.getLoginUser().getUserId();
    UserDeliverOrder deliverOrder = userDeliverOrderService.getOne(new LambdaQueryWrapper<UserDeliverOrder>()
        .eq(UserDeliverOrder::getOrderId, order.getOrderId()).eq(UserDeliverOrder::getUserId, userId));
    DeliverOrderVO deliverOrderVO = mapperFacade.map(deliverOrder, DeliverOrderVO.class);

    // 设置自动确认收货时间
    if (deliverOrder != null && !Objects.isNull(deliverOrder.getDeliveryTime())) {
      Date deliveryTime = deliverOrder.getDeliveryTime();
      LocalDateTime autoConfirmTime = LocalDateTimeUtil.of(deliveryTime).plusDays(15);
      Duration between = LocalDateTimeUtil.between(LocalDateTime.now(), autoConfirmTime);
      long hours = between.toHours();
      long day = hours / 24;
      long hour = hours % 24;
      deliverOrderVO.setAutoConfirmTime(day + "天" + hour + "小时");
    }

    deliverOrderVO.setItems(userDeliverOrderItemService.selectUserDeliverOrderItemVOList(deliverOrder.getOrderId()));
    deliverOrderVO.setDeliverList(userDeliverOrderItemService.getDeliverItemList(order.getOrderId(), deliverOrderVO.getItems()));
    return AjaxResult.success(deliverOrderVO);
  }

  /**
   * 订单结算，每次更换地址时需重新请求此接口
   */
  @PostMapping("/order/settle")
  @ApiOperation(value = "订单结算" , notes = "奖品库里点提货")
  @ApiResponses(
          @ApiResponse(code = 200, message = "success", response = DeliverOrderSettleVO.class)
  )
  public AjaxResult settle(@Valid @RequestBody DeliverOrderParam param) {
    Long userId = SecurityUtils.getLoginUser().getUserId();

    DeliverOrderSettleVO orderSettleVO = new DeliverOrderSettleVO();

    // 收货地址，如果用户选了地址，则此处不做处理
    if (null == param.getAddrId() || 0 == param.getAddrId()) {
      //读取默认地址
      UserAddr addr = userAddrService.getDefaultChannelAddr(userId);
      if (null != addr) {
        orderSettleVO.setAddr(addr);
      }
    }

    // 订单金额计算
    Integer orderAmt = 0;
    Integer freightAmt = 0;


    // 商品数量
    int goodsNum = 0;
    List<UserPrizeStorage> prizeStorageList = new ArrayList<>();
    if (DeliverOrderResourceEnum.PAYMENT.equals(param.getResource())) {
      // 现金支付,设置金额信息
      if (Objects.isNull(param.getGoodsId()) || Objects.isNull(param.getNum())) {
        return AjaxResult.error("商品信息不能为空");
      }
      goodsNum = param.getNum();
      // 获取商品信息
      Goods goods = goodsService.getById(param.getGoodsId());
      GoodsSku goodsSku = goodsSkuService.getById(param.getSkuId());
      if (Objects.isNull(goods)) {
        return AjaxResult.error("商品不存在");
      }
      // 封装商品信息出参
      UserPrizeStorage prizeStorage = new UserPrizeStorage();
      prizeStorage.setGoodsId(goods.getGoodsId());
      prizeStorage.setPicUrl(goods.getPicUrl());
      prizeStorage.setTitle(goods.getTitle());
      prizeStorage.setGoodsNum(goodsNum);
      if (Objects.nonNull(goodsSku)) {
        prizeStorage.setPicUrl(goodsSku.getPicUrl());
        prizeStorage.setSkuId(goodsSku.getSkuId());
        prizeStorage.setProperties(goodsSku.getProperties());

        orderAmt = goodsNum * goodsSku.getValue();
      }else {
        orderAmt = goodsNum * goods.getValue();

      }

      prizeStorageList.add(prizeStorage);
      orderSettleVO.setResource(DeliverOrderResourceEnum.PAYMENT.getValue());
    }else {
      prizeStorageList = userPrizeStorageService.list(new LambdaQueryWrapper<UserPrizeStorage>()
              .eq(UserPrizeStorage::getUserId, userId).eq(UserPrizeStorage::getStatus, PrizeStorageStatusEnum.NOT_DISTRIBUTED)
              .in(UserPrizeStorage::getStorageId, param.getIds()));
      goodsNum = prizeStorageList.stream().mapToInt(UserPrizeStorage::getGoodsNum).sum();
      orderSettleVO.setResource(DeliverOrderResourceEnum.DELIVER.getValue());
    }


    // 计算运费
    UserAddr userAddr = orderSettleVO.getAddr();
    if (Objects.nonNull(userAddr)) {
      // TODO: 4L上线需要调整,后期放开就是取的商品里配的运费模板id
      ShippingTemplateCalculateVO shippingTemplateCalculateVO = shippingTemplateRuleService.getShippingTemplateRuleByTemplateIdAndAreaInfo(shippingTemplateId, userAddr.getProvinceId(), userAddr.getCityId());
      // 无法查到运费模板则默认为0
      if (Objects.nonNull(shippingTemplateCalculateVO)) {

        orderSettleVO.setFreightRemark(shippingTemplateCalculateVO.getRemark());
        orderSettleVO.setFreightType(shippingTemplateCalculateVO.getType());

        if (ShippingTemplateRuleTypeEnum.SHIP.getValue().equals(shippingTemplateCalculateVO.getType())) {
          // 计算运费
          freightAmt = shippingTemplateService.calculateFreightAmt(goodsNum,shippingTemplateCalculateVO);
        }

      }
    }


    orderSettleVO.setOrderAmt(orderAmt);
    orderSettleVO.setFreightAmt(freightAmt);
    orderSettleVO.setPayAmt(orderAmt + freightAmt);
    orderSettleVO.setPrizeList(prizeStorageList);

    // 缓存订单结算对象
    redisCache.setCacheObject(RedisKey.build(RedisKey.USER_DELIVER_ORDER_KEY, userId), orderSettleVO, 10, TimeUnit.MINUTES);
    return AjaxResult.success(orderSettleVO);
  }

  /**
   * 提交订单
   */
  @PostMapping("/order/submit")
  @ApiOperation(value = "提交订单" , notes = "在订单确认页面提交")
  public AjaxResult submit(@RequestBody UserDeliverOrder order) {
    Long userId = SecurityUtils.getLoginUser().getUserId();
    DeliverOrderSettleVO orderSettleVO = redisCache.getCacheObject(RedisKey.build(RedisKey.USER_DELIVER_ORDER_KEY, userId));
    if (null == orderSettleVO) {
      return AjaxResult.error("订单已过期，请重新下单");
    }
    if (null == orderSettleVO.getAddr()) {
      return AjaxResult.error("请填写收货地址");
    }
    String orderId = userDeliverOrderService.submitOrder(userId,order.getMemo(), orderSettleVO);
    JSONObject jsonObject = new JSONObject();
    jsonObject.put("orderId", orderId);
    if (orderSettleVO.getPayAmt() > 0) {
      jsonObject.put("needPay", 1);
    } else {
      jsonObject.put("needPay", 0);
    }
    // 清除缓存的订单
    redisCache.deleteObject(RedisKey.build(RedisKey.USER_DELIVER_ORDER_KEY, userId));

    return AjaxResult.success(jsonObject);
  }


  /**
   * 取消订单
   */
  @PostMapping("/order/cancel")
  @ApiOperation(value = "取消订单" , notes = "在订单列表页面取消")
  public AjaxResult cancel(@RequestBody UserDeliverOrderCancelParam param) {
    userDeliverOrderService.cancelOrder(param.getOrderId());
    return AjaxResult.success("取消成功");
  }

  /**
   * 订单支付
   */
  @PostMapping("/order/pay")
  @ApiOperation(value = "订单支付" , notes = "订单支付")
  public AjaxResult pay(@Valid @RequestBody OrderPayParam param) {
    Long userId = SecurityUtils.getLoginUser().getUserId();
    SysUser sysUser = sysUserService.selectUserById(userId);
    if (StringUtils.isBlank(sysUser.getOpenId())) {
      return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1005);
    }
    UserDeliverOrder deliverOrder = userDeliverOrderService.getById(param.getOrderId());
    JSONObject jsonObject;
    try {
      jsonObject = walletService.pay(BizTypeEnum.DELIVER_ORDER, param.getOrderId(), sysUser.getOpenId(), deliverOrder.getPayAmt(), "盲票--提货订单");
    }catch (ServiceException e) {
      LogUtil.error(logger, e, "根据提货单创建支付单失败。userId:{0},orderId:{1}", new Object[]{userId, param.getOrderId()});
      return AjaxResult.error(e.getMessage());
    }
    return AjaxResult.success(jsonObject);
  }

  @PostMapping("/order/confirm")
  @ApiOperation("订单确认收货")
  public AjaxResult confirm(@RequestBody UserDeliverOrder order){
    Long userId = SecurityUtils.getLoginUser().getUserId();
    UserDeliverOrder userDeliverOrder = userDeliverOrderService.getById(order.getOrderId());
    if (Objects.isNull(userDeliverOrder)) {
      return AjaxResult.error("订单不存在");
    }

    if (!DeliverOrderStatusEnum.NOT_CONFIRM.equals(userDeliverOrder.getStatus())) {
      return AjaxResult.error("订单状态不为待收货");
    }

    if (!userId.equals(userDeliverOrder.getUserId())) {
      return AjaxResult.error("非法操作他人订单");
    }

    // 更新用户提货订单状态为已完成,并且设置收货时间
    UserDeliverOrder param = new UserDeliverOrder();
    param.setOrderId(order.getOrderId());
    param.setStatus(DeliverOrderStatusEnum.FINISHED);
    param.setConfirmTime(new Date());
    userDeliverOrderService.updateById(param);

    return AjaxResult.success();
  }

}
