/*
 *      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.guosen.helpRecord.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.ehcache.core.spi.service.StatisticsService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.modules.guosen.activity.entity.Activity;
import org.springblade.modules.guosen.activity.service.IActivityService;
import org.springblade.modules.guosen.helpRecord.dto.HelpRecordDTO;
import org.springblade.modules.guosen.helpRecord.entity.HelpRecord;
import org.springblade.modules.guosen.helpRecord.mapper.HelpRecordMapper;
import org.springblade.modules.guosen.helpRecord.service.IHelpRecordService;
import org.springblade.modules.guosen.helpRecord.vo.HelpRecordVO;
import org.springblade.modules.guosen.hotDetail.entity.HotDetail;
import org.springblade.modules.guosen.hotDetail.service.IHotDetailService;
import org.springblade.modules.guosen.loginUser.entity.LoginUser;
import org.springblade.modules.guosen.loginUser.service.ILoginUserService;
import org.springblade.modules.guosen.pointsDetail.entity.PointsDetail;
import org.springblade.modules.guosen.pointsDetail.service.IPointsDetailService;
import org.springblade.modules.guosen.present.entity.Present;
import org.springblade.modules.guosen.present.service.IPresentService;
import org.springblade.modules.guosen.production.entity.Production;
import org.springblade.modules.guosen.production.service.IProductionService;
import org.springblade.modules.guosen.rank.service.RankService;
import org.springblade.modules.guosen.userActivityStatistical.dto.UserActivityStatisticalDTO;
import org.springblade.modules.guosen.userActivityStatistical.entity.UserActivityStatistical;
import org.springblade.modules.guosen.userActivityStatistical.service.IUserActivityStatisticalService;
import org.springblade.modules.guosen.userGoods.entity.UserGoods;
import org.springblade.modules.guosen.userGoods.service.IUserGoodsService;
import org.springblade.modules.guosen.userMedal.entity.UserMedal;
import org.springblade.modules.guosen.userMedal.service.IUserMedalService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 *  服务实现类
 *
 * @author BladeX
 * @since 2021-06-17
 */
@Service
public class HelpRecordServiceImpl extends BaseServiceImpl<HelpRecordMapper, HelpRecord> implements IHelpRecordService {

	@Resource @Lazy
	private IActivityService activityService;
	@Resource @Lazy
	private IProductionService productionService;
	@Resource
	private ILoginUserService loginUserService;
	@Resource
	private IPresentService presentService;
	@Resource
	private IPointsDetailService pointsDetailService;
	@Resource
	private IUserMedalService userMedalService;
	@Resource
	private IUserGoodsService userGoodsService;
	@Resource
	private IUserActivityStatisticalService userActivityStatisticalService;
	@Resource
	private RankService rankService;
	@Resource
	private IHotDetailService hotDetailService;

	@Override
	public IPage<HelpRecordVO> selectHelpRecordPage(IPage<HelpRecordVO> page, HelpRecordVO helpRecord) {
		return page.setRecords(baseMapper.selectHelpRecordPage(page, helpRecord));
	}

	@Override
	public IPage<HelpRecordVO> selectHelpRecordVoPage(IPage<HelpRecordVO> page, HelpRecordVO helpRecord) {
		return page.setRecords(baseMapper.selectHelpRecordVoPage(page, helpRecord));
	}

	@Override
	public R doHit(HelpRecordDTO helpRecordDTO) {
		//热力明细
		HotDetail hotDetail = new HotDetail();
		Long receiverId = helpRecordDTO.getReceiverId();
		Long senderId = helpRecordDTO.getSenderId();
		if (receiverId.equals(senderId)) {
			return R.fail("不能给自己助力");
		}
		//A给B的作品打榜
		//获取打榜的活动
		Long activityId = helpRecordDTO.getActivityId();
		Activity activity = activityService.getById(activityId);
		System.out.println("activity==================>"+activity);
		//活动开始时间
		LocalDateTime beginTime = activity.getBeginTime();
		//活动结束时间
		LocalDateTime endTime = activity.getEndTime();
		//当前时间
		LocalDateTime now = LocalDateTime.now();
		if (now.isBefore(beginTime)) {
			return R.fail("当前活动还未开始");

		}
		if (now.isAfter(endTime)) {
			return R.fail("当前活动已结束");

		}
		LoginUser senderUser = loginUserService.getById(senderId);
		if (senderUser == null) {
			return R.fail("用户不存在");
		}
		//获取该活动每人当天最多可打榜多少次
		Integer ticketDays = activity.getTicketDays();
		//获取该用户当天已经打榜了多少次
		Long hitCount = this.getUserDayHitCount(senderId, activityId);
		if (ticketDays <= hitCount) {
			return R.fail("当天已无助力次数，请第二天再助力");
		}
		//开始打榜
		//要增加的热力值
		BigDecimal ticketPoints = activity.getTicketHotValue();
		helpRecordDTO.setTotalHotValue(ticketPoints);

		//如果是作品打榜，作品热力值增加
		if (helpRecordDTO.getType() == 0) {
			Production production = productionService.getById(helpRecordDTO.getProductId());
			BigDecimal productionHotValue = production.getHotValue();
			BigDecimal num = productionHotValue == null || BigDecimal.ZERO.equals(productionHotValue)? ticketPoints : (productionHotValue.add(ticketPoints));
			production.setHotValue(num);
			//作品热力值增加
			rankService.addScore(activityId.toString(), production.getId().toString(), Double.parseDouble(ticketPoints.toString()), 1);
			productionService.updateById(production);
		}
		//个人总热力值增加
		LoginUser loginUser = loginUserService.getById(receiverId);
		BigDecimal loginUserTotalHot = loginUser.getTotalHot();
		BigDecimal num1= loginUserTotalHot == null || BigDecimal.ZERO.equals(loginUserTotalHot)? ticketPoints : ( ticketPoints.add(loginUserTotalHot));
		loginUser.setTotalHot(num1);
		loginUserService.updateById(loginUser);
		//个人活动总热力增加
		UserActivityStatisticalDTO dto = new UserActivityStatisticalDTO();
		dto.setUserId(receiverId);
		dto.setActivityId(activityId);
		dto.setTotalHotValue(ticketPoints);
		userActivityStatisticalService.updateValue(dto);
		//redis缓存，排名
		rankService.addScore(activityId.toString(), receiverId.toString(),Double.parseDouble(ticketPoints.toString()),0);

		//插入打榜记录表中
		helpRecordDTO.setTypeSub(1);
		this.save(helpRecordDTO);

		//插入助力明细
		hotDetail.setNote("打榜助力");
		hotDetail.setUserId(receiverId);
		hotDetail.setType(1);//助力
		hotDetail.setRelationId(helpRecordDTO.getId());
		hotDetail.setHotValue(ticketPoints);
		hotDetailService.save(hotDetail);

		return R.data("打榜成功");
	}

	@Override
	public Long getUserDayHitCount(Long userId, Long activityId) {
		//获取该用户当天已经打榜了多少次
		List<HelpRecord> recordList = baseMapper.selectList(Condition.getQueryWrapper(new HelpRecord()).lambda()
			.eq(HelpRecord::getActivityId, activityId)
			.eq(HelpRecord::getTypeSub, 1)
			.eq(HelpRecord::getSenderId, userId));
		long beginOfDay = DateUtil.beginOfDay(new Date()).getTime();
		long endOfDay = DateUtil.endOfDay(new Date()).getTime();
		long hitCount = recordList.stream().filter(item -> item.getCreateTime().getTime() >= beginOfDay && item.getCreateTime().getTime() <= endOfDay).count();
		return hitCount;
	}

	@Override
	@Transactional
	public R doReward(HelpRecordDTO helpRecordDTO) {
		if (helpRecordDTO.getCount()==null || helpRecordDTO.getCount() <= 0) {
			return R.fail("打赏的礼物数量不正确");
		}
		//获取打赏的礼物
		Present present = presentService.getById(helpRecordDTO.getPresentId());
		//要增加的热力值
		Integer helpRecordDTOCount = helpRecordDTO.getCount();
		BigDecimal hotValue = present.getHotValue().multiply(BigDecimal.valueOf(helpRecordDTOCount));
		//要增加的积分值
		BigDecimal pointsValue = present.getPointsValue().multiply(BigDecimal.valueOf(helpRecordDTOCount));
		//礼物总价格
		BigDecimal totalPresentCash = present.getPrice().multiply(BigDecimal.valueOf(helpRecordDTOCount));
		//活动id
		Long activityId = helpRecordDTO.getActivityId();
		//可提现现金
		Activity activity = activityService.getById(activityId);
		BigDecimal usableCash = activity.getBonusProportion().multiply(hotValue);
		//助力表
		helpRecordDTO.setTotalHotValue(hotValue);
		helpRecordDTO.setTotalCash(totalPresentCash);

		//插入助力表
		helpRecordDTO.setTypeSub(2);
		this.save(helpRecordDTO);
		//积分明细
		PointsDetail pointsDetail = new PointsDetail();
		pointsDetail.setPointsValue(pointsValue);
		pointsDetail.setUserId(helpRecordDTO.getSenderId());
		pointsDetail.setRelationId(helpRecordDTO.getId());
		pointsDetail.setNote("打赏助力");
		pointsDetail.setType(2);//默认为作者打赏
		//作品打赏,作品热力值增加
		if (helpRecordDTO.getType() == 1) {
			pointsDetail.setType(1);//作品打赏
			Production production = productionService.getById(helpRecordDTO.getProductId());
			BigDecimal productionHotValue = production.getHotValue();
			BigDecimal num = productionHotValue == null || BigDecimal.ZERO.equals(productionHotValue)? hotValue : hotValue.add(productionHotValue);
			production.setHotValue(num);
			rankService.addScore(activityId.toString(), production.getId().toString(), Double.parseDouble(hotValue.toString()), 1);
			productionService.updateById(production);
		}
		//插入积分明细
		pointsDetailService.save(pointsDetail);

		if (present.getIsGiveMedal() == 1) {
			//活动赠送勋章,插入勋章记录表
			UserMedal userMedal = userMedalService.getOne(Condition.getQueryWrapper(new UserMedal()).lambda()
				.eq(UserMedal::getUserId, helpRecordDTO.getSenderId())
				.eq(UserMedal::getMedalId, present.getGiveMedalId()));
			if (userMedal != null) {
				Integer count = userMedal.getCount();
				Integer num= count == null ? helpRecordDTOCount : (helpRecordDTOCount + count);
				List<Long> ids = Func.toLongList(userMedal.getActivityIds());
				Set<Long> idsSet = new TreeSet<>(ids);
				idsSet.add(activityId);
				userMedal.setActivityIds(StringUtil.join(idsSet));
				userMedal.setCount(num);
				userMedalService.updateById(userMedal);
			}else{
				UserMedal userMedalSave = new UserMedal();
				userMedalSave.setMedalId(present.getGiveMedalId());
				userMedalSave.setUserId(helpRecordDTO.getSenderId());
				userMedalSave.setCount(helpRecordDTOCount);
				userMedalSave.setActivityIds(activityId.toString());
				userMedalService.save(userMedalSave);
			}
		}
		if (present.getIsSendGoods() == 1) {
			UserGoods userGoods = userGoodsService.getOne(Condition.getQueryWrapper(new UserGoods()).lambda()
				.eq(UserGoods::getUserId, helpRecordDTO.getSenderId())
				.eq(UserGoods::getGoodsId, present.getGoodsId()));
			if (userGoods != null) {
				Integer count = userGoods.getCount();
				Integer num= count == null ? helpRecordDTOCount : (helpRecordDTOCount + count);
				List<Long> ids = Func.toLongList(userGoods.getActivityIds());
				Set<Long> idsSet = new TreeSet<>(ids);
				idsSet.add(activityId);
				userGoods.setActivityIds(StringUtil.join(idsSet));
				userGoods.setCount(num);
				userGoodsService.updateById(userGoods);
			}else{
				//活动赠送实物，插入实物记录表
				UserGoods userGoodsSave = new UserGoods();
				userGoodsSave.setUserId(helpRecordDTO.getSenderId());
				userGoodsSave.setCount(helpRecordDTOCount);
				userGoodsSave.setActivityIds(activityId.toString());
				userGoodsSave.setGoodsId(present.getGoodsId());
				userGoodsService.save(userGoodsSave);
			}

		}
		//被打赏的人个人总热力增加，可用热力也增加
		LoginUser receiver = loginUserService.getById(helpRecordDTO.getReceiverId());
		BigDecimal totalHot = receiver.getTotalHot();
		BigDecimal hotNum= totalHot == null|| BigDecimal.ZERO.equals(totalHot) ? hotValue : hotValue.add(totalHot);
		receiver.setTotalHot(hotNum);
		BigDecimal usableHot = receiver.getUsableHot();
		BigDecimal hotNum1= usableHot == null || BigDecimal.ZERO.equals(usableHot)? hotValue : hotValue.add(usableHot);
		receiver.setUsableHot(hotNum1);
		loginUserService.updateById(receiver);

		//打赏的人个人总积分增加,可用积分也增加
		LoginUser sender = loginUserService.getById(helpRecordDTO.getSenderId());
		BigDecimal totalPoints = sender.getTotalPoints();
		BigDecimal usablePoints = sender.getUsablePoints();
		BigDecimal pointsNum= totalPoints == null || BigDecimal.ZERO.equals(totalPoints)? pointsValue : totalPoints.add(pointsValue);
		sender.setTotalPoints(pointsNum);
		BigDecimal pointsNum1 = usablePoints == null || BigDecimal.ZERO.equals(totalPoints)? pointsValue : usablePoints.add(pointsValue);
		sender.setUsablePoints(pointsNum1);

		//更改被打赏人的活动统计，被打赏人只获得热力值和礼物价值多少现金
		UserActivityStatisticalDTO dto = new UserActivityStatisticalDTO();
		Long receiverId = receiver.getId();
		dto.setUserId(receiverId);
		dto.setActivityId(activityId);
		dto.setTotalHotValue(hotValue);
		dto.setUsableHotValue(hotValue);
		dto.setUsableCash(usableCash);
		dto.setTotalPresentCash(totalPresentCash);
		userActivityStatisticalService.updateValue(dto);

		//redis 缓存
		LoginUser user = loginUserService.getById(receiverId);
		if (user.getUserType() == 1) {
			//是参赛选手才加进缓存进行排行
			rankService.addScore(activityId.toString(), receiverId.toString(), Double.parseDouble(hotValue.toString()), 0);
		}
		//更改打赏人的活动统计，打赏人只获取积分
		UserActivityStatisticalDTO dto1 = new UserActivityStatisticalDTO();
		dto1.setUserId(sender.getId());
		dto1.setActivityId(activityId);
		dto1.setTotalPointsValue(pointsValue);
		dto1.setUsablePointsValue(pointsValue);
		userActivityStatisticalService.updateValue(dto1);

		//插入热力明细表
		HotDetail hotDetail = new HotDetail();
		hotDetail.setUserId(receiverId);
		hotDetail.setNote("打赏助力");
		hotDetail.setType(1);//助力
		hotDetail.setRelationId(helpRecordDTO.getId());
		hotDetail.setHotValue(hotValue);
		hotDetailService.save(hotDetail);


		return R.status(loginUserService.updateById(sender));
	}

}
