package com.ifish.serviceImpl;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.ifish.dao.GoldControlDao;
import com.ifish.dao.GoldExpendRecordDao;
import com.ifish.dao.GoldGetRecordDao;
import com.ifish.dao.GoldRuleDao;
import com.ifish.dao.UserAssetDao;
import com.ifish.dto.JsonResult;
import com.ifish.dto.PageingDto;
import com.ifish.dto.RuleRecordDto;
import com.ifish.dto.UserAssetDto;
import com.ifish.entity.GoldControl;
import com.ifish.entity.GoldControlId;
import com.ifish.entity.GoldExpendRecord;
import com.ifish.entity.GoldGetRecord;
import com.ifish.entity.GoldTask;
import com.ifish.entity.Grade;
import com.ifish.entity.UserAsset;
import com.ifish.enums.AddTypeEnum;
import com.ifish.enums.BooleanEnum;
import com.ifish.enums.GoldExpendTypeEnum;
import com.ifish.enums.GoldGetTypeEnum;
import com.ifish.enums.ResultEnum;
import com.ifish.exception.IfishException;
import com.ifish.hibernate.Pagination;
import com.ifish.service.AsyncTaskService;
import com.ifish.service.CacheService;
import com.ifish.service.GoldService;
import com.ifish.util.IfishUtil;
import com.ifish.util.ResultUtil;
import com.ifish.validator.AddValueParam;
import com.ifish.validator.PageParam;

/**
 * 金币service
 * @author Administrator
 *
 */
@Service
@Transactional
public class GoldServiceImpl implements GoldService {

	@Autowired
	private GoldRuleDao goldRuleDao;
	@Autowired
	private GoldGetRecordDao goldGetRecordDao;
	@Autowired
	private GoldExpendRecordDao goldExpendRecordDao;
	@Autowired
	private GoldControlDao goldControlDao;
	@Autowired
	private UserAssetDao userAssetDao;
	@Autowired
	private CacheService cacheService;
	@Autowired
	private AsyncTaskService asyncTaskService;
	
	/**
	 * 是否加过金币
	 * @param userAsset
	 * @param goldRule
	 * @param isSignin
	 * @return
	 */
	public UserAssetDto getGoldControl(UserAsset userAsset, GoldTask goldRule,boolean isSignin){
		Integer userId = userAsset.getUserId();
		String ruleType = goldRule.getRuleType();
		//日期
		Calendar calendar = Calendar.getInstance();
		//今天
		Date date = calendar.getTime();
		String today = IfishUtil.format1(date);
		//昨天
		calendar.add(Calendar.DAY_OF_MONTH, -1);
		String yesterday = IfishUtil.format1(calendar.getTime());
		//控制信息
		GoldControlId id = new GoldControlId(userId, ruleType);
		GoldControl control = goldControlDao.get(id);
		//加成类型
		String addType = goldRule.getAddType();
		if(control==null){
			//加成一次或每天加成
			if(addType.equals(AddTypeEnum.once.getKey()) || addType.equals(AddTypeEnum.everyDay.getKey())){
				//新增控制今天加过金币
				control = new GoldControl(id, today, date);
				goldControlDao.save(control);
				//加金币
				return addGoldValue(userAsset, goldRule, today, yesterday, isSignin);
			}
		}
		else{
			//每天加成并且今天未加过金币
			if(addType.equals(AddTypeEnum.everyDay.getKey()) && !control.getControlParam().equals(today)){
				//更新今天加过
				control.setControlParam(today);
				control.setUpdateTime(date);
				//加金币
				return addGoldValue(userAsset, goldRule, today, yesterday, isSignin);
			}
		}
		return getUserAssetInfo(userAsset, new BigDecimal(0), today, yesterday);
	}
	
	/**
	 * 加金币并保存记录
	 * @param userAsset
	 * @param goldRule
	 * @param today
	 * @param yesterday
	 * @param isSignin
	 * @return
	 */
	public UserAssetDto addGoldValue(UserAsset userAsset,GoldTask goldRule,String today,String yesterday,boolean isSignin){
		//用户金币
		BigDecimal goldValue = userAsset.getGoldValue();
		//用户经验值
		Integer gradeValue = userAsset.getGradeValue();
		//应加金币
		BigDecimal addValue = goldRule.getAddValue();
		//签到
		if(isSignin){
			//连续签到
			Integer keepNum = userAsset.getKeepSigninNum();
			//昨天已经签到
			if(yesterday.equals(userAsset.getLastSigninDate())){
				keepNum++;
				if(keepNum>7){
					keepNum = 1;
				}
			}
			else{
				keepNum = 1;
			}
			//连续签到奖励每天加1
			addValue = addValue.add(new BigDecimal(keepNum-1));
			//签到信息
			userAsset.setKeepSigninNum(keepNum);
			userAsset.setLastSigninDate(today);
		}
		//金币加成百分比
		BigDecimal goldAddtion = new BigDecimal(0);
		//判定用户等级，根据等级百分比加成金币
		List<Grade> gradeLsit = cacheService.getGradeList();
		for (Grade grade : gradeLsit) {
			if(gradeValue>=grade.getMinValue() && gradeValue<grade.getMaxValue()){
				goldAddtion = grade.getGoldAddition();
				break;
			}
		}
		//金币加成
		if(goldAddtion.compareTo(new BigDecimal(0))>0){
			//额外加成金币
			MathContext mc = new MathContext(2, RoundingMode.HALF_DOWN);
			BigDecimal extraAddValue = goldAddtion.divide(new BigDecimal(100),mc).multiply(addValue);
			//加成后金币
			addValue = addValue.add(extraAddValue);
		}
		//加金币
		userAsset.setGoldValue(goldValue.add(addValue));
		//加金币记录
		Integer userId = userAsset.getUserId();
		String ruleType = goldRule.getRuleType();
		GoldGetRecord goldRecord = new GoldGetRecord(userId, ruleType, addValue, goldRule.getRuleRemark());
		goldGetRecordDao.save(goldRecord);
		//用户动态
		asyncTaskService.saveUserActivity(userId, ruleType);
		return getUserAssetInfo(userAsset, addValue, today, yesterday);
	}
	
	/**
	 * 返回信息封装
	 * @param userAsset
	 * @param addValue
	 * @return
	 */
	@Override
	public UserAssetDto getUserAssetInfo(UserAsset userAsset,BigDecimal addValue,String today,String yesterday){
    	//封装返回值
		UserAssetDto userAssetDto = new UserAssetDto();
		//经验值
		Integer gradeValue = userAsset.getGradeValue();
		//等级信息
		userAssetDto.setGradeValue(gradeValue);
		userAssetDto.setGoldValue(userAsset.getGoldValue());
		userAssetDto.setLastLoginDate(userAsset.getLastLoginDate());
		//连续签到
		Integer keepNum = userAsset.getKeepSigninNum();
		//最后签到
		String lastDay = userAsset.getLastSigninDate();
		//今天是否签到
		if(lastDay.equals(today)){
			userAssetDto.setToDaySignin(BooleanEnum.YES.getKey());
			userAssetDto.setKeepSigninNum(keepNum);
		}
		//最后一次签到是否是昨天
		else if(lastDay.equals(yesterday) && keepNum<7){
			userAssetDto.setKeepSigninNum(keepNum);
		}
		//所加金币
		userAssetDto.setAddValue(addValue);
		//是否砸过金蛋
		userAssetDto.setIsHitGoldenEgg(todayIsHitGoldenEgg(userAsset, today));
		//等级
		for(Grade grade : cacheService.getGradeList()) {
			if(gradeValue>=grade.getMinValue() && gradeValue<grade.getMaxValue()){
				userAssetDto.setGradeNum(grade.getGradeNum());
				userAssetDto.setGradeName(grade.getGradeName());
				break;
			}
		}
    	return userAssetDto;
    }
	
	/**
	 * 今天是否砸过金蛋
	 * @param userAsset
	 * @param today
	 * @return
	 */
	public String todayIsHitGoldenEgg(UserAsset userAsset,String today){
		//查询是否砸过金蛋
		if(userAsset.getKeepSigninNum()==7 && userAsset.getLastSigninDate().equals(today)){
			//砸金蛋控制信息
			GoldControlId goldControlId = new GoldControlId(userAsset.getUserId(), GoldGetTypeEnum.hitGoldenEgg.getKey());
			GoldControl goldControl = goldControlDao.get(goldControlId);
			//未砸过金蛋
			if(goldControl==null || !goldControl.getControlParam().equals(today)){
				return BooleanEnum.NO.getKey();
			}
		}
		return BooleanEnum.YES.getKey();
	}
	
	/**
	 * 根据类型加金币
	 */
	@Override
	public JsonResult<?> addGoldValue(AddValueParam addValueParam) {
		//用户ID
		Integer userId = addValueParam.getUserId();
		UserAsset userAsset = userAssetDao.get(userId);
		if(userAsset==null){
			return new JsonResult<String>(ResultEnum.error402.getKey());
		}
		//规则类型
		String ruleType = addValueParam.getRuleType();
		//签到及砸金蛋接口(有单独的接口)
		if(ruleType.equals(GoldGetTypeEnum.everyDaySignin.getKey()) || ruleType.equals(GoldGetTypeEnum.hitGoldenEgg.getKey())){
			throw new IfishException(ResultEnum.error402);
		}
		GoldTask goldRule = cacheService.getGoldRule(ruleType);
		//不存在和未返回给app的
		if(goldRule==null || !goldRule.getState().equals(BooleanEnum.YES.getKey())){
			return new JsonResult<String>(ResultEnum.error402.getKey());
		}
		return new JsonResult<UserAssetDto>(ResultEnum.success.getKey(), getGoldControl(userAsset, goldRule, false));
	}
	
	/**
	 * 签到
	 */
	@Override
	public JsonResult<?> signin(Integer userId) {
		UserAsset userAsset = userAssetDao.get(userId);
		if(userAsset==null){
			return new JsonResult<String>(ResultEnum.error402.getKey());
		}
		//签到
		String ruleType = GoldGetTypeEnum.everyDaySignin.getKey();
		GoldTask goldRule = cacheService.getGoldRule(ruleType);
		if(goldRule==null || !goldRule.getState().equals(BooleanEnum.YES.getKey())){
			return new JsonResult<String>(ResultEnum.error402.getKey());
		}
		return new JsonResult<UserAssetDto>(ResultEnum.success.getKey(), getGoldControl(userAsset, goldRule, true));
	}

	/**
	 * 砸金蛋
	 */
	@Override
	public JsonResult<?> hitGoldenEgg(Integer userId) {
		UserAsset userAsset = userAssetDao.get(userId);
		if(userAsset==null){
			return new JsonResult<String>(ResultEnum.error402.getKey());
		}
		//砸金蛋
		String ruleType = GoldGetTypeEnum.hitGoldenEgg.getKey();
		GoldTask goldRule = cacheService.getGoldRule(ruleType);
		if(goldRule==null){
			return new JsonResult<String>(ResultEnum.error402.getKey());
		}
		//连续签到7天才能砸金蛋
		Integer keepNum = userAsset.getKeepSigninNum();
		String lastDate = userAsset.getLastSigninDate();
		if(keepNum==7 && lastDate.equals(IfishUtil.format1(new Date()))){
			return new JsonResult<UserAssetDto>(ResultEnum.success.getKey(), getGoldControl(userAsset, goldRule, false));
		}
		else{
			//日期
			Calendar calendar = Calendar.getInstance();
			//今天
			Date date = calendar.getTime();
			String today = IfishUtil.format1(date);
			//昨天
			calendar.add(Calendar.DAY_OF_MONTH, -1);
			String yesterday = IfishUtil.format1(calendar.getTime());
			//查询
			return new JsonResult<UserAssetDto>(ResultEnum.success.getKey(), getUserAssetInfo(userAsset, new BigDecimal(0), today, yesterday));
		}
	}

	/**
	 * 金币获取记录
	 */
	@Override
	public PageingDto<?> getGoldGetRecordByPage(PageParam pageParam) {
		Integer firstResult = pageParam.getFirstResult();
		//根据ID查询获取经验记录
		Pagination<GoldGetRecord> page = goldGetRecordDao.findByCriteria(firstResult, pageParam.getPageSize(), Order.desc("recordId"),Restrictions.eq("userId", pageParam.getUserId()));
		List<GoldGetRecord> goldRecordList = page.getList();
		firstResult+=goldRecordList.size();
		//数据封装
		List<RuleRecordDto> recordList = new ArrayList<RuleRecordDto>();
		for (GoldGetRecord record : goldRecordList) {
				RuleRecordDto recordDto = new RuleRecordDto(record.getRecordId(), record.getAddValue().toString(), record.getRecordRemark(), IfishUtil.format1(record.getCreateTime()));
				recordList.add(recordDto);
		}
		//分页数据封装
		PageingDto<RuleRecordDto> pageingData = new PageingDto<RuleRecordDto>(ResultEnum.success.getKey(), firstResult, page.getTotalCount(), recordList);
		return pageingData;
	}
	/**
	 * 金币消耗记录
	 */
	@Override
	public PageingDto<?> getGoldExpendRecordByPage(PageParam pageParam) {
		Integer firstResult = pageParam.getFirstResult();
		//根据ID查询获取经验记录
		Pagination<GoldExpendRecord> page = goldExpendRecordDao.findByCriteria(firstResult, pageParam.getPageSize(), Order.desc("recordId"),Restrictions.eq("userId", pageParam.getUserId()));
		List<GoldExpendRecord> goldRecordList = page.getList();
		firstResult+=goldRecordList.size();
		//数据封装
		List<RuleRecordDto> recordList = new ArrayList<RuleRecordDto>();
		for (GoldExpendRecord record : goldRecordList) {
				RuleRecordDto recordDto = new RuleRecordDto(record.getRecordId(), record.getExpendValue().toString(), record.getRecordRemark(), IfishUtil.format1(record.getCreateTime()));
				recordList.add(recordDto);
		}
		//分页数据封装
		return new PageingDto<RuleRecordDto>(ResultEnum.success.getKey(), firstResult, page.getTotalCount(), recordList);
	}

	/**
	 * 爱鱼看看打赏
	 */
	@Override
	public JsonResult<?> liveRoomReward(Integer userId, Integer userId2) {
		//自己给自己打赏
		if(userId.equals(userId2)){
			throw new IfishException(ResultEnum.error401);
		}
		//打赏人用户
		UserAsset userAsset = userAssetDao.get(userId);
		if(userAsset==null){
			throw new IfishException(ResultEnum.error402);
		}
		//被打赏人用户
		UserAsset userAsset2 = userAssetDao.get(userId2);
		if(userAsset2==null){
			//之前注册用户赠送20金币
			BigDecimal gold = new BigDecimal(20);
			userAsset2 = new UserAsset(userId2,gold);
			userAssetDao.save(userAsset2);
			//获取记录
			GoldGetRecord getRecord = new GoldGetRecord(userId2, GoldGetTypeEnum.registerGive.getKey(), gold, GoldGetTypeEnum.registerGive.getValue());
			goldGetRecordDao.save(getRecord);
		}
		//爱鱼看看打赏金币
		GoldTask goldTask = goldRuleDao.get(GoldGetTypeEnum.liveRoomPayTour.getKey());
		if(goldTask==null){
			throw new IfishException(ResultEnum.error402);
		}
		//打赏人金币
		BigDecimal goldValue = userAsset.getGoldValue();
		//打赏金币
		BigDecimal addValue = goldTask.getAddValue();
		//打赏人金币不足
		if(goldValue.compareTo(addValue)<0){
			JSONObject json = new JSONObject();
			json.put("goldValue", goldValue);
			return ResultUtil.warn(ResultEnum.warn215.getKey(),json);
		}
		//打赏人扣除金币
		goldValue = goldValue.subtract(addValue);
		userAsset.setGoldValue(goldValue);
		//打赏人金币消耗记录
		GoldExpendRecord goldRecord = new GoldExpendRecord(userId, addValue, GoldExpendTypeEnum.liveRoomPayTour);
		goldExpendRecordDao.save(goldRecord);
		//被打赏人增加金币
		BigDecimal goldValue2 = userAsset2.getGoldValue();
		goldValue2 = goldValue2.add(addValue);
		userAsset2.setGoldValue(goldValue2);
		//金币获取记录
		GoldGetRecord getRecord = new GoldGetRecord(userId2,addValue,GoldGetTypeEnum.liveRoomPayTour);
		goldGetRecordDao.save(getRecord);
		//打赏金币数量
		BigDecimal totalGoldValue = goldGetRecordDao.getQuestionPayTourGoldValue(userId2);
		//返回金币剩余数量
		JSONObject json = new JSONObject();
		json.put("userGoldValue", goldValue);
		json.put("rewardValue", addValue);
		json.put("totalGoldValue", totalGoldValue);
		return ResultUtil.success(json);
	}

}
