package com.qs.mp.web.controller.api.channel.mall;

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.TicketBox;
import com.qs.mp.admin.domain.vo.ShippingTemplateCalculateVO;
import com.qs.mp.admin.service.ITicketBoxService;
import com.qs.mp.channel.domain.Channel;
import com.qs.mp.channel.domain.ChannelOrderDetail;
import com.qs.mp.channel.domain.vo.ChannelOrderInfoVO;
import com.qs.mp.channel.domain.vo.ChannelOrderItemVO;
import com.qs.mp.channel.service.IChannelOrderDetailService;
import com.qs.mp.common.domain.DeliveryCompany;
import com.qs.mp.common.enums.*;
import com.qs.mp.common.service.IDeliveryCompanyService;
import com.qs.mp.common.service.IShippingTemplateRuleService;
import com.qs.mp.common.service.IShippingTemplateService;
import com.qs.mp.common.utils.StringUtils;
import com.qs.mp.system.domain.SysUser;
import com.qs.mp.system.service.ISysUserService;
import com.qs.mp.user.domain.UserAddr;
import com.qs.mp.channel.domain.ChannelCart;
import com.qs.mp.channel.domain.ChannelOrder;
import com.qs.mp.channel.domain.ChannelOrderItem;
import com.qs.mp.channel.domain.param.ChannelOrderParam;
import com.qs.mp.channel.domain.param.OrderPayParam;
import com.qs.mp.channel.domain.vo.ChannelCartVO;
import com.qs.mp.channel.domain.vo.ChannelOrderSettleVO;
import com.qs.mp.channel.domain.vo.ChannelOrderVO;
import com.qs.mp.user.domain.UserPrizeStorage;
import com.qs.mp.user.service.IUserAddrService;
import com.qs.mp.channel.service.IChannelCartService;
import com.qs.mp.channel.service.IChannelOrderItemService;
import com.qs.mp.channel.service.IChannelOrderService;
import com.qs.mp.channel.service.IChannelService;
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.exception.ServiceException;
import com.qs.mp.common.utils.LogUtil;
import com.qs.mp.framework.redis.RedisKey;
import com.qs.mp.pay.service.IWalletService;
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.time.Duration;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;
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/channel/mall")
@Api(tags = "渠道盲票商城订单接口")
public class ChannelOrderController extends BaseApiController {


  @Autowired
  private IChannelCartService channelCartService;

  @Autowired
  private IChannelOrderService channelOrderService;

  @Autowired
  private IChannelOrderItemService channelOrderItemService;

  @Autowired
  private ITicketBoxService ticketBoxService;

  @Autowired
  private IUserAddrService userAddrService;

  @Autowired
  private MapperFacade mapperFacade;

  @Autowired
  private IWalletService walletService;

  @Autowired
  private IChannelService channelService;

  @Autowired
  private IDeliveryCompanyService deliveryCompanyService;

  @Autowired
  private IChannelOrderDetailService channelOrderDetailService;

  @Autowired
  private ISysUserService sysUserService;

  @Autowired
  private RedisCache redisCache;

  @Autowired
  private IShippingTemplateRuleService shippingTemplateRuleService;

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

  @Autowired
  private IShippingTemplateService shippingTemplateService;



  /**
   * 订单列表
   */
  @PostMapping("/order/list")
  @ApiOperation(value = "订单列表" , notes = "获取所有订单信息")
  @ApiResponses(
          @ApiResponse(code = 200, message = "成功", response = ChannelOrderVO.class)
  )
  public TableDataInfo list(@RequestBody JSONObject param) {
    Long channelId = SecurityUtils.getLoginUser().getChannelId();
    Integer status = param.getInteger("status");
    startPage();
    List<ChannelOrder> channelOrders = channelOrderService.list(
        new LambdaQueryWrapper<ChannelOrder>().eq(ChannelOrder::getChannelId, channelId)
            .eq(null != status, ChannelOrder::getStatus, status)
            .orderByDesc(ChannelOrder::getCreatedTime));
    List<ChannelOrderVO> channelOrderVOList = mapperFacade.mapAsList(channelOrders, ChannelOrderVO.class);
    for (ChannelOrderVO channelOrderVO : channelOrderVOList) {
    	List<ChannelOrderItem> itemList = channelOrderItemService.list(new LambdaQueryWrapper<ChannelOrderItem>()
     	          .eq(ChannelOrderItem::getOrderId, channelOrderVO.getOrderId()));

     	 List<ChannelOrderItemVO> itemVOList = mapperFacade.mapAsList(itemList, ChannelOrderItemVO.class);
         channelOrderVO.setItems(itemVOList);
    }
    TableDataInfo rspData = getDataTable(channelOrders);
    rspData.setRows(channelOrderVOList);
    return rspData;
  }

  /**
   * 订单详情
   */
  @PostMapping("/order/detail")
  @ApiOperation(value = "订单详情" , notes = "在订单列表页面查看详情")
  public AjaxResult query(@RequestBody ChannelOrder order) {
    Long channelId = SecurityUtils.getLoginUser().getChannelId();
    ChannelOrder channelOrder = channelOrderService.getOne(new LambdaQueryWrapper<ChannelOrder>()
        .eq(ChannelOrder::getOrderId, order.getOrderId()).eq(ChannelOrder::getChannelId, channelId));
    ChannelOrderInfoVO channelOrderVO = mapperFacade.map(channelOrder, ChannelOrderInfoVO.class);

    // 设置自动确认收货的时间;
    if (channelOrderVO != null && Objects.nonNull(channelOrderVO.getDeliveryTime())) {
      Date deliveryTime = channelOrderVO.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;
      channelOrderVO.setAutoConfirmTime(day + "天" + hour + "小时");
    }


    if(null != channelOrderVO && null != channelOrderVO.getDeliveryId()) {
      DeliveryCompany deliveryCompany = deliveryCompanyService.getById(channelOrderVO.getDeliveryId());
      channelOrderVO.setDeliveryCompany(deliveryCompany);
    }
    List<ChannelOrderItem> itemList = channelOrderItemService.list(new LambdaQueryWrapper<ChannelOrderItem>()
        .eq(ChannelOrderItem::getOrderId, channelOrderVO.getOrderId()));

    List<ChannelOrderItemVO> itemVOList = mapperFacade.mapAsList(itemList, ChannelOrderItemVO.class);
    if(null != itemVOList && itemVOList.size() > 0) {
      for(ChannelOrderItemVO itemVO : itemVOList) {
        if(null != itemVO && org.apache.commons.lang3.StringUtils.isNotBlank(itemVO.getBoxId())
            && org.apache.commons.lang3.StringUtils.isNotBlank(itemVO.getOrderId())) {
          LambdaQueryWrapper<ChannelOrderDetail> detailQueryWrapper = new LambdaQueryWrapper<ChannelOrderDetail>();
          detailQueryWrapper.eq(ChannelOrderDetail::getOrderId, itemVO.getOrderId());
          detailQueryWrapper.eq(ChannelOrderDetail::getBoxId, itemVO.getBoxId());
          List<ChannelOrderDetail> detailList = channelOrderDetailService.list(detailQueryWrapper);
          itemVO.setDetailList(detailList);
        }
      }
    }
    channelOrderVO.setItems(itemVOList);
    return AjaxResult.success(channelOrderVO);
  }

  /**
   * 订单结算，每次更换地址或优惠券时需重新请求此接口
   */
  @PostMapping("/order/settle")
  @ApiOperation(value = "订单结算" , notes = "购物车里点结算或者单个盲票组商品上点立即购买")
  @ApiResponses(
          @ApiResponse(code = 200, message = "success", response = ChannelOrderSettleVO.class)
  )
  public AjaxResult settle(@Valid @RequestBody ChannelOrderParam param) {
    Long userId = SecurityUtils.getLoginUser().getUserId();
    Long channelId = SecurityUtils.getLoginUser().getChannelId();
    Channel channel = channelService.getById(channelId);
    if (channel.getStatus() == ChannelStatusEnum.OFF) {
      return AjaxResult.error("账号异常");
    }
    ChannelOrderSettleVO orderSettleVO = new ChannelOrderSettleVO();
    // 收货地址，如果用户选了地址，则此处不做处理
    if (null == param.getAddrId() || 0 == param.getAddrId()) {
      //读取默认地址
      UserAddr addr = userAddrService.getDefaultChannelAddr(userId);
      if (null != addr) {
        orderSettleVO.setAddr(addr);
      }
    }

    // 订单金额计算
    Integer orderAmt = 0;
    Integer pkgNum = 0;
    if (!CollectionUtils.isEmpty(param.getCartIds())){
      // 购物车里下单的
      List<ChannelCart> channelCarts = channelCartService.listByIds(param.getCartIds());
      for (ChannelCart channelCart : channelCarts) {
        TicketBox ticketBox = ticketBoxService.getById(channelCart.getBoxId());
        orderAmt += ticketBox.getPkgSalePrice() * channelCart.getOrderNum();
        ChannelCartVO cartVO = mapperFacade.map(ticketBox, ChannelCartVO.class);
        cartVO.setCartId(channelCart.getCartId());
        cartVO.setOrderNum(channelCart.getOrderNum());
        orderSettleVO.getItems().add(cartVO);
        pkgNum += channelCart.getOrderNum();
      }
    } else {
      TicketBox ticketBox = ticketBoxService.getById(param.getBoxId());
      if (Objects.nonNull(param.getIsPre()) && param.getIsPre() == 1) {
        // 预购票金额计算处理
        orderAmt = ticketBox.getPkgPrePrice() * param.getOrderNum();
        // 设置类型
        if (TicketTypeEnum.OFFLINE.equals(ticketBox.getType())) {
          orderSettleVO.setType(ChannelOrderTypeEnum.OFFLINE_PRE.getValue());
        } else {
          orderSettleVO.setType(ChannelOrderTypeEnum.ONLINE_PRE.getValue());
        }
      } else {
        // 非预购票金额计算处理
        orderAmt += ticketBox.getPkgSalePrice() * param.getOrderNum();
        // 设置类型
        orderSettleVO.setType(ChannelOrderTypeEnum.RETAIL.getValue());
      }
      ChannelCartVO cartVO = mapperFacade.map(ticketBox, ChannelCartVO.class);
      cartVO.setOrderNum(param.getOrderNum());
      orderSettleVO.getItems().add(cartVO);
      pkgNum += param.getOrderNum();

    }


    // 运费计算
    Integer freightAmt = 0;
    // 计算运费
    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(pkgNum, shippingTemplateCalculateVO);
        }
      }
    }


    // 设置运费
    orderSettleVO.setFreightAmt(freightAmt);

    orderSettleVO.setOrderAmt(orderAmt);
    // 当前没有运费和优惠，实付金额=订单金额 + 运费金额
    orderSettleVO.setPayAmt(orderAmt + freightAmt);
    orderSettleVO.setPkgNum(pkgNum);

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

  /**
   * 提交订单
   */
  @PostMapping("/order/submit")
  @ApiOperation(value = "提交订单" , notes = "在订单确认页面提交")
  public AjaxResult submit(@RequestBody ChannelOrder order) {
    Long channelId = SecurityUtils.getLoginUser().getChannelId();
    Channel channel = channelService.getById(channelId);
    if (channel.getCertifyStatus() != ChannelCertifyStatusEnum.CERTIFIED) {
      LogUtil.info(logger, "账号未认证。channelId:{0}", channelId);
      return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1016);
    }
    ChannelOrderSettleVO orderSettleVO = redisCache.getCacheObject(RedisKey.build(RedisKey.CHANNEL_ORDER_KEY, channelId));
    if (null == orderSettleVO) {
      return AjaxResult.error("订单已过期，请重新下单");
    }
    if (null == orderSettleVO.getAddr()) {
      return AjaxResult.error("收货地址缺失，请重新下单");
    }
    String orderId = channelOrderService.submitOrder(channelId, order.getMemo(), orderSettleVO);

    // 清除缓存的订单
    redisCache.deleteObject(RedisKey.build(RedisKey.CHANNEL_ORDER_KEY, channelId));

    return AjaxResult.success(orderId);
  }


  /**
   * 取消订单
   */
  @PostMapping("/order/cancel")
  @ApiOperation(value = "取消订单" , notes = "在订单列表页面取消")
  public AjaxResult cancel(@RequestBody ChannelOrder order) {
    Long channelId = SecurityUtils.getLoginUser().getChannelId();
    channelOrderService.cancelOrder(channelId, order.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);
    String channelOpenId = "";
    if (StringUtils.isNotBlank(param.getOpenId())) {
      channelOpenId = param.getOpenId();
    } else {
      channelOpenId = sysUser.getChannelOpenId();
    }
    if (StringUtils.isBlank(channelOpenId)) {
      return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1005);
    }
    ChannelOrder channelOrder = channelOrderService.getById(param.getOrderId());
    JSONObject jsonObject;
    try {
      jsonObject = walletService.pay(BizTypeEnum.CHANNEL_ORDER, param.getOrderId(), channelOpenId, channelOrder.getPayAmt(), channelOrder.getTitle());
    }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 ChannelOrder order){
    Long channelId = SecurityUtils.getLoginUser().getChannelId();
    ChannelOrder channelOrder = channelOrderService.getById(order.getOrderId());
    if (Objects.isNull(channelOrder)) {
      return AjaxResult.error("订单不存在");
    }

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

    if (!channelId.equals(channelOrder.getChannelId())) {
      return AjaxResult.error("非法操作他人订单");
    }
    // 确认收货
    channelOrderService.confirm(order);

    return AjaxResult.success();
  }
}
