package org.springblade.gateway.goods_gateway.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.jsonwebtoken.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springblade.common.utils.BeanPropertyUtil;
import org.springblade.common.utils.IPUtils;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.gateway.active_gateway.service.AppActiveProductService;
import org.springblade.gateway.goods_gateway.exception.HelpGoodsException;
import org.springblade.gateway.goods_gateway.service.AppHelpGoodsService;
import org.springblade.gateway.point_gateway.enums.CmccPayStatus;
import org.springblade.gateway.point_gateway.enums.PointTypeEnum;
import org.springblade.payment.cmcc.exception.CmccRequestException;
import org.springblade.payment.cmcc.request.CmccDectOrderRequest;
import org.springblade.payment.cmcc.request.CmccPlaceOrderRequest;
import org.springblade.payment.cmcc.util.CmccUtil;
import org.springblade.sing.active.entity.ActiveHelpRecord;
import org.springblade.sing.goods.entity.GoodsRecord;
import org.springblade.sing.goods.entity.HelpGoods;
import org.springblade.sing.goods.enums.GoodsRecordType;
import org.springblade.sing.goods.service.IGoodsRecordService;
import org.springblade.sing.goods.service.IHelpGoodsService;
import org.springblade.sing.point.entity.CmccPointRecord;
import org.springblade.sing.point.entity.PointRecord;
import org.springblade.sing.point.service.ICmccPointRecordService;
import org.springblade.sing.point.service.IPointRecordService;
import org.springblade.sing.user.entity.LoginUser;
import org.springblade.sing.user.service.ILoginUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Arrays;

/**
 * @Author: Silent
 * @Description
 * @Date: Created in 14:28 2021/11/10
 * @Modified By:
 */
@Service
@Slf4j
public class AppHelpGoodsServiceImpl implements AppHelpGoodsService {
	@Autowired
	private ILoginUserService loginUserService;
	@Autowired
	private IPointRecordService pointRecordService;
	@Autowired
	private IHelpGoodsService helpGoodsService;
	@Autowired
	private ICmccPointRecordService cmccPointRecordService;
	@Autowired
	private IGoodsRecordService goodsRecordService;
	@Autowired
	private AppActiveProductService appActiveProductService;
	@Autowired
	private HttpServletRequest request;

	/**
	 * 移动积分兑换道具
	 * @param cmccPointRecord
	 * @return
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public void exchangeProps(CmccPointRecord cmccPointRecord,CmccDectOrderRequest cmccDectOrderRequest,Long productId) {
		//获取道具商品
		HelpGoods helpGoods = helpGoodsService.getById(cmccPointRecord.getHelpGoodsId());
		Assert.notNull(helpGoods,"没有找到该道具");

		//判断道具是否上架
		Assert.isTrue(Integer.valueOf(1).equals(helpGoods.getStatus()),"该道具未上架");

		//获取用户信息
		LoginUser loginUser = loginUserService.getById(cmccPointRecord.getUserId());
		Assert.notNull(loginUser,"没有找到该用户");

		//用户兑换道具次数检测，并且添加兑换记录
		userExchangeCountCheck(cmccPointRecord, helpGoods, loginUser);

		//先助力
		ActiveHelpRecord activeHelpRecord = new ActiveHelpRecord();
		activeHelpRecord.setProductId(productId);
		activeHelpRecord.setUserId(loginUser.getId());
		activeHelpRecord.setHelpGoodsId(helpGoods.getId());
		activeHelpRecord.setIp(IPUtils.getRealIp(request));
		activeHelpRecord.setVoteCount(helpGoods.getVotePointRate().longValue());
		appActiveProductService.activeHelp(activeHelpRecord,ObjectUtils.getIfNull(cmccPointRecord.getPhone(),loginUser::getPhone));

		//助力之后判断是否需要移动积分兑换(防止先兑换之后，助力不成功问题)
		cmccPointExchange(cmccPointRecord, cmccDectOrderRequest, helpGoods, loginUser);
	}

	/**
	 * 用户兑换道具次数检测，并且添加兑换记录
	 * @param cmccPointRecord
	 * @param helpGoods
	 * @param loginUser
	 */
	@Override
	public void userExchangeCountCheck(CmccPointRecord cmccPointRecord, HelpGoods helpGoods, LoginUser loginUser) {
		//判断用户今天购买该商品次数是否超过限制(-1标识不限制次数)
		if(!helpGoods.getTotal().equals(-1L)){
			//今日购买次数
			Long count = userHelpGoodsExchangeCount(loginUser.getId(), helpGoods.getId());
			//购买次数>=允许购买的次数
			if((cmccPointRecord.getNum().longValue() + count)> helpGoods.getTotal()){
				throw new HelpGoodsException("您购买次数超过上限");
			}
		}
		//添加道具兑换记录
		GoodsRecord goodsRecord = new GoodsRecord();
		goodsRecord.setUserId(loginUser.getId());
		goodsRecord.setHelpGoodsId(helpGoods.getId());
		goodsRecord.setNum(cmccPointRecord.getNum().longValue());
		goodsRecord.setType(GoodsRecordType.HELP_GOODS_EXCHANGE);
		Assert.isTrue(goodsRecordService.save(goodsRecord),"兑换失败");
	}

	/**
	 * 移动积分兑换
	 * @param cmccPointRecord
	 * @param cmccDectOrderRequest
	 * @param helpGoods
	 * @param loginUser
	 */
	@Override
	public void cmccPointExchange(CmccPointRecord cmccPointRecord, CmccDectOrderRequest cmccDectOrderRequest, HelpGoods helpGoods, LoginUser loginUser) {
		//对接移动积分接口
		if(ObjectUtils.isNotEmpty(helpGoods.getPoint()) && helpGoods.getPoint().longValue()>0L){
			Assert.notNull(cmccDectOrderRequest.getOutOrderId(),"订单号不能为空");

			//查询移动订单记录
			CmccPointRecord oldCmccPointRecord = cmccPointRecordService.getOne(Wrappers.<CmccPointRecord>lambdaQuery().eq(CmccPointRecord::getOutOrderId, cmccDectOrderRequest.getOutOrderId()));
			Assert.notNull(oldCmccPointRecord,"没有找到移动支付订单");

			//判断是否是同一个道具
			if(ObjectUtils.notEqual(helpGoods.getId(),oldCmccPointRecord.getHelpGoodsId())){
				throw new HelpGoodsException("您购买的道具和您的订单不相同");
			}

			//判断数量是否相同
			if(ObjectUtils.notEqual(cmccPointRecord.getNum(),oldCmccPointRecord.getNum())){
				throw new HelpGoodsException("您购买的道具和您的订单数量不相同");
			}

			//添加移动积分兑换记录
			PointRecord pointRecord = new PointRecord();
			pointRecord.setPoint(oldCmccPointRecord.getPoint());
			pointRecord.setHelpGoodsId(helpGoods.getId());
			pointRecord.setUserId(loginUser.getId());
			pointRecord.setPointType(PointTypeEnum.CMCC_POINT_EXCHANGE);
			Assert.isTrue(pointRecordService.save(pointRecord),"兑换失败");

			//设置状态为支付成功
			oldCmccPointRecord.setPayStatus(CmccPayStatus.SUCCESS);

			//更新支付状态
			Assert.isTrue(cmccPointRecordService.updateById(oldCmccPointRecord));

			//移动支付逻辑
			cmccDectOrderRequest.setMobile(oldCmccPointRecord.getPhone());
			try {
				CmccUtil.dectOrder(cmccDectOrderRequest);
			} catch (CmccRequestException e) {
				//支付失败逻辑
				throw new HelpGoodsException(e.getMessage());
			}
		}
	}

	/**
	 * 用户今日道具兑换次数
	 * @param userId 用户ID
	 * @param helpGoodsId 道具ID
	 * @return
	 */
	@Override
	public Long userHelpGoodsExchangeCount(Long userId, Long helpGoodsId) {
		Long count = MapUtil.getLong(goodsRecordService.getMap(Wrappers.<GoodsRecord>query()
			.select(new StringBuilder("ifnull(sum(")
				.append(BeanPropertyUtil.getFieldNameToUnder(GoodsRecord::getNum))
				.append("),0) as count")
				.toString())
			.lambda()
			.eq(GoodsRecord::getUserId, userId)
			.eq(GoodsRecord::getHelpGoodsId, helpGoodsId)
			.eq(GoodsRecord::getType, GoodsRecordType.HELP_GOODS_EXCHANGE.name())
			.last(new StringBuilder("and date_format(")
				.append(BeanPropertyUtil.getFieldNameToUnder(PointRecord::getCreateTime))
				.append(",\"%Y-%m-%d\")=\"")
				.append(DateUtil.format(DateUtil.now(), "yyyy-MM-dd").trim()).append("\"").toString())), "count");
		return count;
	}

	/**
	 * 创建道具订单
	 * @param cmccPointRecord
	 */
	@Override
	public void createPropsOrder(CmccPointRecord cmccPointRecord, CmccPlaceOrderRequest cmccPlaceOrderRequest) {
		//获取道具id
		HelpGoods helpGoods = helpGoodsService.getById(cmccPointRecord.getHelpGoodsId());
		Assert.notNull(helpGoods,"没有找到该道具");

		//判断道具是否上架
		Assert.isTrue(Integer.valueOf(1).equals(helpGoods.getStatus()),"该道具未上架");

		//判断道具是否需要积分支付
		if(BigDecimal.ZERO.equals(helpGoods.getPoint())){
			throw new HelpGoodsException("该道具不需要积分支付");
		}

		//设置状态为待支付
		cmccPointRecord.setPayStatus(CmccPayStatus.WAIT);
		//生成随机订单号
		cmccPointRecord.setOutOrderId(IdUtil.randomUUID());
		//设置积分
		cmccPointRecord.setPoint(cmccPointRecord.getNum().multiply(helpGoods.getPoint()));

		//设置商品属性
		CmccPlaceOrderRequest.ProductItem productItem = new CmccPlaceOrderRequest.ProductItem();
		productItem.setNum(cmccPointRecord.getNum().toString());
		productItem.setProductId(helpGoods.getCmccGoodsId());

		//设置商品列表
		cmccPlaceOrderRequest.setProductItemList(JSONObject.toJSONString(Arrays.asList(productItem)));
		cmccPlaceOrderRequest.setMobile(cmccPointRecord.getPhone());
		//移动积分价值需要 x 1.2(我不知道为啥)
		cmccPlaceOrderRequest.setPoints(cmccPointRecord.getNum().multiply(helpGoods.getPoint()).toString());

		Assert.isTrue(cmccPointRecordService.save(cmccPointRecord),"创建订单失败");

		// TODO 移动订单创建逻辑
		//设置请求属性
		cmccPlaceOrderRequest.setOutOrderId(cmccPointRecord.getOutOrderId());
		try {
			CmccUtil.placeOrder(cmccPlaceOrderRequest);
		} catch (CmccRequestException e) {
			throw new HelpGoodsException(e.getMessage());
		}
	}
}
