package com.platform.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.platform.annotation.IgnoreAuth;
import com.platform.annotation.LoginUser;
import com.platform.cache.J2CacheUtils;
import com.platform.entity.*;
import com.platform.enums.ResultCodeEnum;
import com.platform.exception.CommonBaseException;
import com.platform.service.*;
import com.platform.util.ApiBaseAction;
import com.platform.utils.CharUtil;
import com.platform.utils.CommonDataUtils;

import com.platform.utils.StringUtils;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;

import static com.platform.interceptor.AuthorizationInterceptor.LOGIN_USER_KEY;

/**
 * API优惠券管理
 *
 * @author lipengjun
 * @email 939961241@qq.com
 * @gitee https://gitee.com/fuyang_lipengjun/platform
 * @date 2017-03-23 15:31
 */
@Api(tags = "优惠券")
@RestController
@RequestMapping("/api/coupon")
@Slf4j
public class ApiCouponController extends ApiBaseAction {
    @Autowired
    private ApiUserService apiUserService;
    @Autowired
    private ApiCouponService apiCouponService;
    @Autowired
    private ApiUserCouponService apiUserCouponService;
    @Autowired
    private ApiProductService apiProductService;
    @Autowired
    private ApiCartService apiCartService;

    /**
     * 获取优惠券列表
     */
    @ApiOperation(value = "获取用户下面所有优惠券列表")
    @PostMapping("/list")
    public Object list(HttpServletRequest request) {
        Long userId = (Long) request.getAttribute(LOGIN_USER_KEY);
        if(null == userId){
            logger.warn("获取用户ID失败，无法获取用户下所有优惠券列表");
        }
        Map<String , Object> param = new HashMap<>();
        param.put("user_id", userId);
        List<CouponVo> couponVos = apiCouponService.queryUserCoupons(param);
        log.info("第一次返回的可用优惠券列表为:{}", JSON.toJSONString(couponVos));
        List<CouponVo> validVos = new ArrayList<>();
        if(!CollectionUtils.isEmpty(couponVos)){
            for (CouponVo couponVo : couponVos){
                //这里的优惠券状态为生效中,使用状态为可用的
                if(couponVo.getCouponStatus() == 2 && couponVo.getUseStatus() == 1){
                    validVos.add(couponVo);
                }
            }
        }
        log.info("最终返回的可用优惠券列表为:{}", JSON.toJSONString(validVos));
        return toResponsSuccess(validVos);

    }

    /**
     * 获取用户下当年已经失效的优惠券
     */
    @ApiOperation(value = "获取用户下当年已经失效的优惠券")
    @PostMapping("/getInvalidCoupons")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前页码", paramType = "query", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", paramType = "query", required = true, dataType = "Long"),
    })
    public Result getInvalidCoupons(@RequestParam(name = "pageNum") long pageNum,
                                    @RequestParam(name = "pageSize") long pageSize) {
        Long userId = (Long) request.getAttribute(LOGIN_USER_KEY);
        if(null == userId){
            logger.warn("获取用户ID失败，无法获取用户下所有已经失效优惠券列表");
        }
        IPage<CouponVo> resultPage = apiCouponService.getInvalidCouponByYear(userId , pageNum , pageSize);
        return Result.success(CommonDataUtils.assembleResult(resultPage.getTotal() , resultPage.getPages() , resultPage.getCurrent(),
                resultPage.getRecords()));
    }

    /**
     * 获商家下面所有的优惠券
     */
    @ApiOperation(value = "获商家下面所有的优惠券-无需登录")
    @GetMapping("/getListUnAuth")
    @IgnoreAuth
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前页码", paramType = "query", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", paramType = "query", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "brandId", value = "商家Id", paramType = "query", required = true, dataType = "String"),
    })
    public Result getListByBrandWithoutAuth(@RequestParam(name = "pageNum") Long pageNum,
                                 @RequestParam(name = "pageSize") Long pageSize,
                                 @RequestParam(name = "brandId") String  brandId , HttpServletRequest request) {
        if (null == pageNum || null == pageSize || org.apache.commons.lang.StringUtils.isBlank(brandId)) {
            throw new CommonBaseException(ResultCodeEnum.D3001);
        }
        IPage<CouponVo> resultPage = apiCouponService.getCouponPageByBrand(brandId , pageNum , pageSize);
        if(null == resultPage){
            throw new CommonBaseException(ResultCodeEnum.D101 , "获取店铺下面优惠券列表出现异常");
        }
        return Result.success(CommonDataUtils.assembleResult(resultPage.getTotal() , resultPage.getPages() , resultPage.getCurrent(),
                resultPage.getRecords()));
    }

    /**
     * 获商家下面所有的优惠券
     */
    @ApiOperation(value = "获商家下面所有的优惠券")
    @GetMapping("/getListByBrand")
//    @IgnoreAuth
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNum", value = "当前页码", paramType = "query", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", paramType = "query", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "brandId", value = "商家Id", paramType = "query", required = true, dataType = "String"),
    })
    public Result getListByBrand(@RequestParam(name = "pageNum") Long pageNum,
                                 @RequestParam(name = "pageSize") Long pageSize,
                                 @RequestParam(name = "brandId") String  brandId , HttpServletRequest request) {

        if (null == pageNum || null == pageSize || org.apache.commons.lang.StringUtils.isBlank(brandId)) {
            throw new CommonBaseException(ResultCodeEnum.D3001);
        }
        IPage<CouponVo> resultPage = apiCouponService.getCouponPageByBrand(brandId , pageNum , pageSize);
        if(null == resultPage){
            throw new CommonBaseException(ResultCodeEnum.D101 , "获取店铺下面优惠券列表出现异常");
        }
        List<CouponVo> couponVoList = resultPage.getRecords();
        List<CouponVo> resultCouponVoList = new ArrayList<>();
        if(!CollectionUtils.isEmpty(couponVoList)){
            Long userId = getUserId();
            if(null == userId){
                throw new CommonBaseException(ResultCodeEnum.D101 , "获取不到客户ID");
            }
            for(CouponVo couponVo : couponVoList){
                log.info("获取优惠券ID={},用户id={}", couponVo.getId() , userId);
                UserCouponVo dbUserCouponVo = apiUserCouponService.getByUserIdAndCouponId(userId , couponVo.getId());
                if(null != dbUserCouponVo){
                    couponVo.setHasReceived(1);
                    log.info("用户[{}]已经领取优惠券[{}]" , userId , couponVo.getId());
                }else{
                    couponVo.setHasReceived(0);
                }
                resultCouponVoList.add(couponVo);
            }
        }
        if(!CollectionUtils.isEmpty(resultCouponVoList)){
            log.info("替换新的优惠券列表");
            resultPage.setRecords(resultCouponVoList);
        }

        return Result.success(CommonDataUtils.assembleResult(resultPage.getTotal() , resultPage.getPages() , resultPage.getCurrent(),
                resultPage.getRecords()));
    }


    /**
     * 根据ID获取优惠券详情
     */
    @ApiOperation(value = "根据ID获取优惠券详情")
    @GetMapping("/getCouponById")
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = "couponId", value = "优惠券Id", paramType = "query", required = true, dataType = "Integer"),
    })
    public Result getCouponById(@RequestParam(name = "couponId") Integer  couponId ) {

        if(null == couponId){
            logger.info("优惠券ID不能为空");
            throw new CommonBaseException(ResultCodeEnum.D3001);
        }
        CouponVo couponVo = apiCouponService.queryObject(couponId);
        return Result.success(couponVo);
    }

    /**
     * 根据商品获取可用优惠券列表
     */
    @ApiOperation(value = "根据商品获取可用优惠券列表")
    @PostMapping("/listByGoods")
    public Object listByGoods(@RequestParam(defaultValue = "cart") String type, @LoginUser UserVo loginUser) {
        BigDecimal goodsTotalPrice = new BigDecimal(0.00);
        if (type.equals("cart")) {
            Map<String , Object> param = new HashMap();
            param.put("user_id", loginUser.getUserId());
            List<CartVo> cartList = apiCartService.queryList(param);
            //获取购物车统计信息
            for (CartVo cartItem : cartList) {
                if (null != cartItem.getChecked() && 1 == cartItem.getChecked()) {
                    goodsTotalPrice = goodsTotalPrice.add(cartItem.getRetail_price().multiply(new BigDecimal(cartItem.getNumber())));
                }
            }
        } else { // 是直接购买的
            BuyGoodsVo goodsVo = (BuyGoodsVo) J2CacheUtils.get(J2CacheUtils.SHOP_CACHE_NAME, "goods" + loginUser.getUserId() + "");
            ProductVo productInfo = apiProductService.queryObject(goodsVo.getProductId());
            //商品总价
            goodsTotalPrice = productInfo.getRetail_price().multiply(new BigDecimal(goodsVo.getNumber()));
        }

        // 获取可用优惠券
        Map<String , Object> param = new HashMap<>();
        param.put("user_id", loginUser.getUserId());
        param.put("coupon_status", 1);
        List<CouponVo> couponVos = apiCouponService.queryUserCoupons(param);
        List<CouponVo> useCoupons = new ArrayList<>();
        List<CouponVo> notUseCoupons = new ArrayList<>();
        for (CouponVo couponVo : couponVos) {
            if (goodsTotalPrice.compareTo(couponVo.getMinGoodsAmount()) >= 0) { // 可用优惠券
                couponVo.setEnabled(1);
                useCoupons.add(couponVo);
            } else {
                couponVo.setEnabled(0);
                notUseCoupons.add(couponVo);
            }
        }
        useCoupons.addAll(notUseCoupons);
        return toResponsSuccess(useCoupons);
    }

    /**
     * 兑换优惠券
     */
    @ApiOperation(value = "领券优惠券")
    @PostMapping("exchange")
    @Transactional(rollbackFor = Exception.class)
    public Result exchange(@RequestParam(name = "couponId") Integer couponId , HttpServletRequest request) {
        if(null == couponId){
            throw new CommonBaseException(ResultCodeEnum.D3001);
        }
        CouponVo latestCoupon = apiCouponService.selectCouponForUpdate(couponId);
        if(null == latestCoupon){
            log.error("优惠券不存在");
            throw new CommonBaseException(ResultCodeEnum.D101 , "优惠券不存在");
        }
        if(latestCoupon.getCouponStatus().compareTo(2) != 0){
           log.error("优惠券[{}]状态为非生效状态:{}，无法领取" , latestCoupon.getId() , latestCoupon.getCouponStatus());
           return Result.failure("优惠券非生效中，无法领取");
        }

//        Date nowTime = new Date();
        LocalDateTime nowTime = LocalDateTime.now();
        if(nowTime.compareTo(latestCoupon.getUseStartDate()) < 0){
            //优惠券开始使用时间在当前时间之后，也就是未生效，但是状态还未刷新
            log.error("优惠券[{}]未生效，不能领取" , latestCoupon.getId());
            return Result.failure("优惠券未生效");
        }
        if(nowTime.compareTo(latestCoupon.getUseEndDate()) > 0){
            //优惠券截止使用时间在当前时间之前，说明优惠券已经过了有效期
            log.error("优惠券[{}]已经过了有效期，不能领取" , latestCoupon.getId());
            return Result.failure("优惠券已经过了有效期");
        }
        if(null != latestCoupon.getReceiveNumber() && latestCoupon.getReceiveNumber().compareTo(latestCoupon.getNumber()) == 0){
            log.error("优惠券[{}]领取数量已经达到上限，无法领取" , latestCoupon.getId());
            return Result.failure("券已发完");
        }
        Long userId = (Long) request.getAttribute(LOGIN_USER_KEY);
        if(null == userId){
            logger.warn("获取用户ID失败，无法领取优惠券");
            throw new CommonBaseException(ResultCodeEnum.D101 , "获取用户ID失败，无法领取优惠券");
        }
        UserCouponVo dbUserCouponVo = apiUserCouponService.getByUserIdAndCouponId(userId , couponId);
        if(null != dbUserCouponVo){
            logger.warn("该用户已经领取过此优惠券");
            throw new CommonBaseException(ResultCodeEnum.D101 , "该用户已经领取过此优惠券");
        }
        dbUserCouponVo = new UserCouponVo();
        dbUserCouponVo.setUserId(userId);
        dbUserCouponVo.setCouponId(couponId);
        dbUserCouponVo.setAddTime(new Date());
        apiUserCouponService.save(dbUserCouponVo);

        long recNum = (null == latestCoupon.getReceiveNumber() ? 0 : latestCoupon.getReceiveNumber());
        recNum += 1;
        latestCoupon.setReceiveNumber(recNum);
        latestCoupon.setUpdateTime(LocalDateTime.now());
        apiCouponService.update(latestCoupon);
        log.info("更新优惠券[{}]的领取数成功");
        return Result.success("领取成功",null);
    }

    /**
     * 　　填写手机号码，领券
     */
    @ApiOperation(value = "领券优惠券")
    @PostMapping("newuser")
    public Object newuser(@LoginUser UserVo loginUser) {
        JSONObject jsonParam = getJsonRequest();
        //
        String phone = jsonParam.getString("phone");
        Integer smscode = jsonParam.getInteger("smscode");
        // 校验短信码
        SmsLogVo smsLogVo = apiUserService.querySmsCodeByUserId(loginUser.getUserId());
        if (null != smsLogVo && smsLogVo.getSms_code() != smscode) {
            return toResponsFail("短信校验失败");
        }
        // 更新手机号码
        if (!StringUtils.isNullOrEmpty(phone)) {
            if (phone.equals(loginUser.getMobile())) {
                loginUser.setMobile(phone);
                apiUserService.update(loginUser);
            }
        }
        // 判断是否是新用户
        if (!StringUtils.isNullOrEmpty(loginUser.getMobile())) {
            return toResponsFail("当前优惠券只能新用户领取");
        }
        // 是否领取过了
        Map params = new HashMap();
        params.put("user_id", loginUser.getUserId());
        params.put("send_type", 4);
        List<CouponVo> couponVos = apiCouponService.queryUserCoupons(params);
        if (null != couponVos && couponVos.size() > 0) {
            return toResponsFail("已经领取过，不能重复领取");
        }
        // 领取
        Map couponParam = new HashMap();
        couponParam.put("send_type", 4);
        CouponVo newCouponConfig = apiCouponService.queryMaxUserEnableCoupon(couponParam);
        if (null != newCouponConfig) {
            UserCouponVo userCouponVo = new UserCouponVo();
            userCouponVo.setAddTime(new Date());
            userCouponVo.setCouponId(newCouponConfig.getId());
            userCouponVo.setCouponNumber(CharUtil.getRandomString(12));
            userCouponVo.setUserId(loginUser.getUserId());
            apiUserCouponService.save(userCouponVo);
            return toResponsSuccess(userCouponVo);
        } else {
            return toResponsFail("领取失败");
        }
    }

    /**
     * 　　转发领取红包
     */
    @ApiOperation(value = "转发领取红包")
    @PostMapping("transActivit")
    public Object transActivit(@LoginUser UserVo loginUser, String sourceKey, Long referrer) {
        JSONObject jsonParam = getJsonRequest();
        // 是否领取过了
        Map params = new HashMap();
        params.put("user_id", loginUser.getUserId());
        params.put("send_type", 2);
        params.put("source_key", sourceKey);
        List<CouponVo> couponVos = apiCouponService.queryUserCoupons(params);
        if (null != couponVos && couponVos.size() > 0) {
            return toResponsObject(2, "已经领取过", couponVos);
        }
        // 领取
        Map couponParam = new HashMap();
        couponParam.put("send_type", 2);
        CouponVo newCouponConfig = apiCouponService.queryMaxUserEnableCoupon(couponParam);
        if (null != newCouponConfig) {
            UserCouponVo userCouponVo = new UserCouponVo();
            userCouponVo.setAddTime(new Date());
            userCouponVo.setCouponId(newCouponConfig.getId());
            userCouponVo.setCouponNumber(CharUtil.getRandomString(12));
            userCouponVo.setUserId(loginUser.getUserId());
            userCouponVo.setSourceKey(sourceKey);
            userCouponVo.setReferrer(referrer);
            apiUserCouponService.save(userCouponVo);
            //
            List<UserCouponVo> userCouponVos = new ArrayList();
            userCouponVos.add(userCouponVo);
            //
            params = new HashMap();
            params.put("user_id", loginUser.getUserId());
            params.put("send_type", 2);
            params.put("source_key", sourceKey);
            couponVos = apiCouponService.queryUserCoupons(params);
            return toResponsSuccess(couponVos);
        } else {
            return toResponsFail("领取失败");
        }
    }
}
