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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qs.mp.admin.domain.Ticket;
import com.qs.mp.admin.domain.TicketBox;
import com.qs.mp.admin.domain.TicketBoxGoods;
import com.qs.mp.admin.domain.TicketPackage;
import com.qs.mp.admin.domain.vo.TicketBoxGoodsListVO;
import com.qs.mp.admin.service.ITicketBoxGoodsService;
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.Channel;
import com.qs.mp.channel.domain.ChannelOrder;
import com.qs.mp.channel.domain.param.OrderPayParam;
import com.qs.mp.channel.domain.vo.PromoterVO;
import com.qs.mp.channel.service.IPromoterUserService;
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.AppSourceEnum;
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.enums.TicketBoxStatusEnum;
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;

    @Autowired
    private ITicketBoxGoodsService ticketBoxGoodsService;

    @Autowired
    private IPromoterUserService promoterUserService;


    /**
     * 订单结算，每次更换优惠券时需重新请求此接口
     */
    @PostMapping("/order/settle")
    @ApiOperation(value = "订单结算", notes = "单个盲票商品上点立即购买")
    @ApiResponses(
        @ApiResponse(code = 200, message = "OK", response = TicketOrderSettleVO.class)
    )
    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;
            }


            // 设置用户关联的推广员信息
            QueryWrapper<Channel> promoterQueryWrapper = new QueryWrapper<>();
            promoterQueryWrapper.eq("t1.is_deleted", 0);
            promoterQueryWrapper.eq("t1.user_id", userId);
            promoterQueryWrapper.eq("t4.ticket_id", ticket.getTicketId());
            promoterQueryWrapper.eq("t5.is_deleted", 0);
            PromoterVO promoter = promoterUserService.getPromoterByQueryWrapper(promoterQueryWrapper);
            orderSettleVO.setPromoter(promoter);

        } else {
            // 线上购票
            ticketBox = ticketBoxService.getById(param.getBoxId());
            orderAmt = ticketBox.getSalePrice() * param.getOrderNum();
        }

        if (TicketBoxStatusEnum.STOP.getValue().equals(ticketBox.getStatus().getValue())) {
            return AjaxResult.error("盲票已停售！");
        }

        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());

        AppSourceEnum appSourceEnum = AppSourceEnum.getByValue(param.getAppSource());
        orderSettleVO.setAppId(appSourceEnum.getAppId());
        // 从指定门店盲票下单
        orderSettleVO.setChannelId(param.getSiteId());

        QueryWrapper<TicketBoxGoodsListVO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("t1.is_deleted",0);
        queryWrapper.eq("t2.is_deleted", 0);
        queryWrapper.eq("t1.box_id",param.getBoxId());
        List<TicketBoxGoodsListVO> ticketBoxGoodsListVOS = ticketBoxService.listTicketGoodsByQueryWrapper(queryWrapper);
        if (!CollectionUtils.isEmpty(ticketBoxGoodsListVOS)) {
            TicketBoxGoodsListVO ticketBoxGoodsListVO = ticketBoxGoodsListVOS.get(0);
            orderSettleVO.setGoodsPicUrl(ticketBoxGoodsListVO.getPicUrl());
            orderSettleVO.setGoodsTitle(ticketBoxGoodsListVO.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 repeatSubmitKey = RedisKey.build(RedisKey.LIMIT_USER_REPEAT_SUBMIT, userId, orderSettleVO.getBoxId());
        TicketBox ticketBox = ticketBoxService.getById(orderSettleVO.getBoxId());
        if (TicketBoxStatusEnum.STOP.getValue().equals(ticketBox.getStatus().getValue())) {
            return AjaxResult.error("盲票已停售！");
        }
        //免费的盲票每个用户只能领取一次
        if (orderSettleVO.getPayAmt() == 0 && orderSettleVO.getDiscountAmt() == 0){
            int orderCount = userTicketOrderService.count(
                    new LambdaQueryWrapper<UserTicketOrder>().eq(UserTicketOrder::getUserId, userId).eq(UserTicketOrder::getBoxId, orderSettleVO.getBoxId()));
            if (orderCount > 0) {
                return AjaxResult.error("您已领取过盲票！");
            }
        }
        //限制前端重复提交请求
        String repeatSubmitRecord = redisCache.getCacheObject(repeatSubmitKey);
        if (StringUtils.isNotBlank(repeatSubmitRecord)) {
            return AjaxResult.error("请稍候点击！");
        }else {
            redisCache.setCacheObject(repeatSubmitKey, "用户userId:"+userId+"已请求", 3, TimeUnit.SECONDS);
        }

        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));
        if (orderSettleVO.getPayAmt() > 0) {
            if (AppSourceEnum.MP.getAppId().equals(orderSettleVO.getAppId())) {
                return AjaxResult.error("支付系统升级中，请稍后再试");
            }
        }

        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);
        String openId = "";
        if (param.getPayType() == 1) {
            if (StringUtils.isBlank(sysUser.getAliuserId())) {
                return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1026);
            }
        } else {
            AppSourceEnum appSourceEnum = AppSourceEnum.getByValue(param.getAppSource());
            if (AppSourceEnum.MSDQ.equals(appSourceEnum)) {
                if (StringUtils.isBlank(sysUser.getMsdqOpenId())) {
                    return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1005);
                }
                openId = sysUser.getMsdqOpenId();
            } else {
                if (StringUtils.isBlank(sysUser.getOpenId())) {
                    return AjaxResult.error(ErrorCodeEnum.ERROR_CODE_1005);
                }
                openId = sysUser.getOpenId();
            }
        }

        UserTicketOrder ticketOrder = userTicketOrderService.getById(param.getOrderId());
        JSONObject jsonObject;
        try {
            if (param.getPayType() == 1) {
                // 支付宝支付
                jsonObject = walletService.directAliPay(BizTypeEnum.TICKET_ORDER, param.getOrderId(), sysUser.getAliuserId(),
                    ticketOrder.getPayAmt(), ticketOrder.getTitle());
            } else {
                // 微信支付
                jsonObject = walletService.pay(BizTypeEnum.TICKET_ORDER, param.getOrderId(), openId,
                    ticketOrder.getPayAmt(), ticketOrder.getTitle(), param.getAppSource());
            }
        } 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;
    }

}
