/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.api.controller;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springblade.common.cache.ParamCache;
import org.springblade.common.constant.CommonConstant;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.modules.api.service.IApiService;
import org.springblade.modules.finance.entity.Order;
import org.springblade.modules.finance.entity.OrderGrant;
import org.springblade.modules.finance.service.IOrderConsignService;
import org.springblade.modules.finance.service.IOrderGrantService;
import org.springblade.modules.finance.service.IOrderService;
import org.springblade.modules.shopping.entity.Consign;
import org.springblade.modules.shopping.entity.ConsignConfig;
import org.springblade.modules.shopping.entity.GoodsAttributes;
import org.springblade.modules.shopping.service.IConsignConfigService;
import org.springblade.modules.shopping.service.IConsignService;
import org.springblade.modules.shopping.service.IGoodsAttributesService;
import org.springblade.modules.shopping.service.IGoodsService;
import org.springblade.modules.shopping.vo.ConsignVO;
import org.springblade.modules.shopping.vo.GoodsVO;
import org.springblade.modules.shopping.wrapper.ConsignWrapper;
import org.springblade.modules.shopping.wrapper.GoodsAttributesWrapper;
import org.springblade.modules.shopping.wrapper.GoodsWrapper;
import org.springblade.modules.system.entity.UserApp;
import org.springblade.modules.system.service.IRegionService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 控制器
 *
 * @author xuwei
 * @since 2022-02-12
 */
@RestController
@AllArgsConstructor
@RequestMapping(CommonConstant.API_URL)
@Api(value = "抢购接口", tags = "03.抢购接口")
public class Api03Controller extends BladeController {
	private static final Logger log = LoggerFactory.getLogger(Api03Controller.class);

	private final IGoodsService goodsService;
	private final IGoodsAttributesService goodsAttributesService;
	private final IConsignConfigService consignConfigService;
	private final IConsignService consignService;
	public static IRegionService regionService;
	private final IApiService apiService;
	private final IOrderGrantService orderGrantService;
	private final IOrderConsignService orderConsignService;
	private final IOrderService orderService;

	@GetMapping("/consignConfig-list")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "抢购场次", notes = "获取缓存数据，失效时间2分钟")
	public R<List<ConsignConfig>> consignConfigList() {
		return R.data(consignConfigService.selectCacheList());
	}


	@GetMapping("/consign-page")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "抢购专区-查询所有数据", notes = "传入consign")
	public R<List<ConsignVO>> ConsignPage(@ApiParam(value = "场次开始时间", required = true) @RequestParam String time,
										  Query query) {
		Consign consign = new Consign();
		consign.setIsSale(2); //上架
		consign.setIsDelivery(1); //未交割
		String ymd = DateUtil.format(DateUtil.now(), DateUtil.PATTERN_DATE);
		String startTime = ymd + " " + time;
		IPage<Consign> pages = consignService.page(Condition.getPage(query),
			Condition.getQueryWrapper(consign)
				.lt("start_time", startTime)
				.orderByAsc("start_time"));
		return R.data(ConsignWrapper.build().listVO(pages.getRecords()));
	}

	@GetMapping("/consign-list")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "抢购专区-展示两条数据", notes = "传入consign")
	public R<List<ConsignVO>> ConsignList(@ApiParam(value = "场次ID", required = true) @RequestParam Long id) {
		return R.data(consignService.selectConsignList(id));
	}

	@GetMapping("/consign-detailById")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "浏览商品", notes = "传入consign主键ID")
	public R<ConsignVO> detail(@ApiParam(value = "抢购主键", required = true) @RequestParam String consignId,
							   @ApiParam(value = "用户ID", required = true) @RequestParam Long userId) {
		Consign detail = consignService.getById(consignId);
		if (ObjectUtil.isNull(detail)){
			return R.fail("无商品数据！");
		}
		ConsignVO consignVO = ConsignWrapper.build().entityVO(detail);
		GoodsVO vo = GoodsWrapper.build().entityVO(goodsService.getById(detail.getGoodsId()));
		if (vo != null){
			//获取商品属性参数
			List<GoodsAttributes> list = goodsAttributesService.list(Wrappers.<GoodsAttributes>lambdaQuery().eq(GoodsAttributes::getGoodsId, vo.getId()));
			consignVO.setGoodsAttributes(GoodsAttributesWrapper.build().listVO(list));
			//商品规格项和值
			consignVO.setSpecItems(apiService.specItemsList(vo.getId()));
			consignVO.setGoodsImg(vo.getGoodsImg());
			consignVO.setGallery(vo.getGallery());
			consignVO.setGoodsLabel(vo.getGoodsLabel());
			consignVO.setTextImg(vo.getTextImg());
		}
		/**
		 * 1 去 useID 和 场次id  ----(预授权表)（有数据  或不有.）
		 *   1.1  有。。。该预授单的状态---==1---加  订单表--是否有 该用户，该场次-的订单-4-（完成）--数量（剩余可抢）》1
		 */
		Kv kv = consignGrant(userId, consignVO.getConsignConfigId());
		Integer isGrant = kv.getInt("isGrant");
		consignVO.setIsGrant(isGrant);
		consignVO.setOrderNo(kv.getStr("orderNo"));
		consignVO.setScoreCount(kv.getInt("scoreCount"));
		consignVO.setEnableCount(kv.getInt("enableCount"));
		if (3 == isGrant){
			return R.data(consignVO,"您本场抢购次数已用完！");
		}
		return R.data(consignVO);
	}

	/**
	 * 查询用户预授权数据
	 * isGrant
	 * 	为2 已授权 需要返回授权订单号
	 *  为1 未授权 返回的为空
	 * @param userId 用户
	 * @param consignConfigId 场次
	 * @return Kv
	 */
	private Kv consignGrant(Long userId, Long consignConfigId){
		Kv kv = Kv.create();
		Integer count = orderConsignService.selectUserCount(userId, consignConfigId);
		log.info("用户【" + userId + "】在场次【" + consignConfigId + "】已抢购次数为：" + count);
		UserApp userApp = new UserApp();
		UserApp query = userApp.selectOne(Wrappers.<UserApp>lambdaQuery().eq(UserApp::getUserId,userId));
		log.info("用户【" + userId + "】基本数据:" + query.toString());
		//应该查询所有授权的数包含：已授权 + 解冻 （应该是当天 + 场次 + 用户）
		List<OrderGrant> selectGrantList = orderGrantService.selectGrant(consignConfigId, userId);
		log.info("用户【" + userId + "】授权数据:" + selectGrantList);
		log.info("用户【" + userId + "】userApp.getIsAuth() :" + query.getEnableAuth());
		if(query.getEnableAuth() != 2){
			log.info("用户【" + userId + "】为普通用户，判断信誉积分数据");
			double k = (double)query.getCreditScore() / 100;
			int scoreCount = NumberUtil.roundDown(k, 2).intValue();
			int consignCount = Integer.parseInt(ParamCache.getValue(CommonConstant.DEFAULT_CONDIGN_COUNT));
			if (scoreCount > consignCount){
				scoreCount = consignCount;
			}
			log.info("用户【" + userId + "】为信誉分可抢次数为：" + scoreCount);
			int enableCount = scoreCount - count; //信誉分可抢次数 - 已抢次数 = 可抢次数
			log.info("用户【" + userId + "】为实际可抢次数为：" + enableCount);
			kv.put("scoreCount", scoreCount);
			kv.put("enableCount", scoreCount);
			if (enableCount <= 0){
				kv.put("isGrant", 3);
				kv.put("orderNo", "");
				return kv;
			}
		}else{
			kv.put("scoreCount", 999);
			kv.put("enableCount", 999);
		}
		//授权订单总条数
		int grantCount = 0;
		List<String> authNos = new ArrayList<>();
		//授权订单号
		String orderNo = "";
		for (OrderGrant orderGrant: selectGrantList) {
			grantCount = grantCount + orderGrant.getNum();
			authNos.add(orderGrant.getAuthNo());
			//获取剩余的授权数量
			if (orderGrant.getNowNum() > 0){
				orderNo = orderGrant.getOrderNo();
			}
		}
		log.info("查询用户【" + userId + "】在场次【" + consignConfigId + "】是否有已授权成功的授权总数量：" + grantCount);
		if (selectGrantList.size() > 0){
			//有已授权的数据 查询关联的已授权的订单数
			List<Order> list = orderService.list(Wrappers.<Order>lambdaQuery().in(Order::getGrantNo, authNos));
			log.info("查询用户【" + userId + "】在场次【" + consignConfigId + "】成功是否有已授权的订单数据条数：" + list.size());
			//该授权号订单条数 小于 授权总数量 则为已授权
			if (list.size() < grantCount){
				kv.put("isGrant", 2);
				kv.put("orderNo", orderNo);
				return kv;
			}
		}
		log.info("用户【" + userId + "】为未授权，请发起授权");
		kv.put("isGrant", 1);
		kv.put("orderNo", "");
		return kv;
	}


	@GetMapping("/consign-turnout")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "参与人数", notes = "虚拟数")
	public R turnout() {
		UserApp userApp = new UserApp();
		Integer i = userApp.selectCount(Wrappers.lambdaQuery());
		Float ratio = Float.valueOf(ParamCache.getValue(CommonConstant.DEFAULT_CONDIGN_TURNOUT));
		BigDecimal total = NumberUtil.mul(i, ratio);
		Double c = RandomUtil.randomDouble(0.5, 1);
		BigDecimal val = NumberUtil.mul(total, c);
		return R.data(NumberUtil.roundStr(String.valueOf(val), 0));
	}

}
