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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qs.mp.admin.domain.Ticket;
import com.qs.mp.admin.domain.TicketBox;
import com.qs.mp.admin.domain.TicketPackage;
import com.qs.mp.admin.service.ITicketBoxService;
import com.qs.mp.admin.service.ITicketPackageService;
import com.qs.mp.admin.service.ITicketService;
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.enums.BizTypeEnum;
import com.qs.mp.common.enums.ErrorCodeEnum;
import com.qs.mp.common.enums.MqTopicType;
import com.qs.mp.common.exception.ServiceException;
import com.qs.mp.common.pulsar.PulsarClientService;
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.UserTicketOrder;
import com.qs.mp.user.domain.param.TicketOrderParam;
import com.qs.mp.user.domain.vo.TicketOrderSettleVO;
import com.qs.mp.user.domain.vo.UserCoupon4OrderVO;
import com.qs.mp.user.domain.vo.UserCouponVO;
import com.qs.mp.user.domain.vo.UserShareVO;
import com.qs.mp.user.service.IUserCouponService;
import com.qs.mp.user.service.IUserTicketOrderService;
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.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.apache.pulsar.client.api.PulsarClientException;
import org.springframework.beans.factory.annotation.Autowired;
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/ticket")
@Api(tags = "用户端购买盲票接口")
@AllArgsConstructor
public class UserTicketOrderController extends BaseApiController {


    @Autowired
    private ITicketBoxService ticketBoxService;

    @Autowired
    private IUserTicketOrderService userTicketOrderService;

    @Autowired
    private ITicketService ticketService;

    @Autowired
    private IUserCouponService userCouponService;

    @Autowired
    private IWalletService walletService;

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private MapperFacade mapperFacade;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private PulsarClientService pulsarClientService;

    @Autowired
    private ITicketPackageService ticketPackageService;


    /**
     * 订单结算，每次更换优惠券时需重新请求此接口
     */
    @PostMapping("/order/settle")
    @ApiOperation(value = "订单结算", notes = "单个盲票商品上点立即购买")
    public AjaxResult settle(@Valid @RequestBody TicketOrderParam param) {
        if (StringUtils.isBlank(param.getTicketId()) && StringUtils.isBlank(param.getBoxId())) {
            return AjaxResult.error("参数缺失");
        }
        Long userId = SecurityUtils.getLoginUser().getUserId();

        TicketOrderSettleVO orderSettleVO = new TicketOrderSettleVO();


        // 订单金额计算
        Integer orderAmt = 0;
        Integer discountAmt = 0;
        TicketBox ticketBox;
        if (StringUtils.isNotBlank(param.getTicketId())) {
            // 线下扫码购票
            Ticket ticket = ticketService.getById(param.getTicketId());
            ticketBox = ticketBoxService.getById(ticket.getBoxId());
            orderAmt = ticketBox.getSalePrice();

            // 预付票设置金额为0
            TicketPackage ticketPackage = ticketPackageService.getById(ticket.getPkgId());
            if (ticketPackage.getIsPre() == 1) {
                orderAmt = 0;
            }
        } else {
            // 线上购票
            ticketBox = ticketBoxService.getById(param.getBoxId());
            orderAmt = ticketBox.getSalePrice() * param.getOrderNum();
        }

        if (param.getAutoCoupon() == 1) {
            List<UserCouponVO> userCouponVOList = userCouponService.queryUserCouponList(userId, orderAmt, ticketBox);
            if (!CollectionUtils.isEmpty(userCouponVOList)) {
                // 只考虑使用单张券
                orderSettleVO.getCouponList().add(mapperFacade.map(userCouponVOList.get(0), UserCoupon4OrderVO.class));
                discountAmt = userCouponVOList.get(0).getDiscount();
            }
        } else if (!CollectionUtils.isEmpty(param.getUserCouponIds())) {
            // 查询指定券
            List<UserCouponVO> userCouponVOList = userCouponService.listTicketOrderCouponByIds(param.getUserCouponIds());
            if (!CollectionUtils.isEmpty(userCouponVOList)) {
                // 只考虑使用单张券
                orderSettleVO.getCouponList().add(mapperFacade.map(userCouponVOList.get(0), UserCoupon4OrderVO.class));
                discountAmt = userCouponVOList.get(0).getDiscount();
            }
        }

        orderSettleVO.setOrderAmt(orderAmt);
        orderSettleVO.setDiscountAmt(discountAmt);
        // 当前没有运费和优惠，实付金额=订单金额
        orderSettleVO.setPayAmt(orderAmt - discountAmt);
        orderSettleVO.setOrderNum(param.getOrderNum());
        orderSettleVO.setBoxId(ticketBox.getBoxId());
        orderSettleVO.setTicketId(param.getTicketId());
        orderSettleVO.setPicUrl(ticketBox.getPicUrl());
        orderSettleVO.setTitle(ticketBox.getTitle());

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

    /**
     * 提交订单
     */
    @PostMapping("/order/submit")
    @ApiOperation(value = "提交订单", notes = "在订单确认页面提交")
    public AjaxResult submit(@RequestBody UserShareVO userShareVO) {
        Long userId = SecurityUtils.getLoginUser().getUserId();
        TicketOrderSettleVO orderSettleVO = redisCache.getCacheObject(RedisKey.build(RedisKey.USER_TICKET_ORDER_KEY, userId));
        if (null == orderSettleVO) {
            return AjaxResult.error("订单已过期，请重新下单");
        }
        String orderId = userTicketOrderService.submitOrder(userId, orderSettleVO, userShareVO);
        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_TICKET_ORDER_KEY, userId));

        return AjaxResult.success(jsonObject);
    }


    /**
     * 取消订单
     */
    @PostMapping("/order/cancel")
    @ApiOperation(value = "取消订单", notes = "在订单列表页面取消")
    public AjaxResult cancel(@RequestBody ChannelOrder order) {
        userTicketOrderService.cancelOrder(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);
        if (StringUtils.isBlank(sysUser.getOpenId())) {
            return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1005);
        }
        UserTicketOrder ticketOrder = userTicketOrderService.getById(param.getOrderId());
        JSONObject jsonObject;
        try {
            jsonObject = walletService.pay(BizTypeEnum.TICKET_ORDER, param.getOrderId(), sysUser.getOpenId(), ticketOrder.getPayAmt(), ticketOrder.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/coupon/list")
    @ApiOperation(value = "查询可用优惠券", notes = "在下单页面选择")
    @ApiResponses(
            @ApiResponse(code = 200, message = "成功", response = UserCouponVO.class)
    )
    public AjaxResult listCoupon(@RequestBody TicketOrderParam param) {
        Long userId = SecurityUtils.getUserId();
        TicketOrderSettleVO orderSettleVO = redisCache.getCacheObject(RedisKey.build(RedisKey.USER_TICKET_ORDER_KEY, userId));
        if (null == orderSettleVO) {
            return AjaxResult.error("订单已过期，请重新下单");
        }
        TicketBox ticketBox = ticketBoxService.getById(orderSettleVO.getBoxId());
        List<UserCouponVO> userCouponVOList = userCouponService.queryUserCouponList(userId, orderSettleVO.getOrderAmt(), ticketBox);

        // 设置选中状态
        for (UserCouponVO userCouponVO : userCouponVOList) {
            if (!CollectionUtils.isEmpty(orderSettleVO.getCouponList())) {
                for (UserCoupon4OrderVO userCoupon4OrderVO : orderSettleVO.getCouponList()) {
                    if (userCoupon4OrderVO.getId().equals(userCouponVO.getId())) {
                        userCouponVO.setChecked(true);
                        break;
                    }
                }
            }
        }
        return AjaxResult.success(userCouponVOList);
    }


    @PostMapping("/order/coupon/listPage")
    @ApiOperation(value = "查询可用优惠券,分页", notes = "在下单页面选择")
    @ApiResponses(
            @ApiResponse(code = 200, message = "成功", response = UserCouponVO.class)
    )
    public TableDataInfo listPageCoupon(@RequestBody TicketOrderParam param) {
        Long userId = SecurityUtils.getUserId();
        TicketOrderSettleVO orderSettleVO = redisCache.getCacheObject(RedisKey.build(RedisKey.USER_TICKET_ORDER_KEY, userId));
        if (null == orderSettleVO) {
            return getErrorDataTable("订单已过期，请重新下单");
        }
        TicketBox ticketBox = ticketBoxService.getById(orderSettleVO.getBoxId());
        startPage();
        List<UserCouponVO> userCouponVOList = userCouponService.queryUserCouponList(userId, orderSettleVO.getOrderAmt(), ticketBox);

        // 设置选中状态
        for (UserCouponVO userCouponVO : userCouponVOList) {
            if (!CollectionUtils.isEmpty(orderSettleVO.getCouponList())) {
                for (UserCoupon4OrderVO userCoupon4OrderVO : orderSettleVO.getCouponList()) {
                    if (userCoupon4OrderVO.getId().equals(userCouponVO.getId())) {
                        userCouponVO.setChecked(true);
                        break;
                    }
                }
            }
        }
        List<UserCouponVO> countUserCouponVOList = userCouponService.queryUserCouponList(userId, orderSettleVO.getOrderAmt(), ticketBox);
        TableDataInfo dataTable = getDataTable(userCouponVOList);
        dataTable.setTotal(countUserCouponVOList.size());
        return dataTable;
    }

}
