package com.ym.mec.biz.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import com.ym.mec.biz.dal.dto.TaskRewardsRulesDto;
import com.ym.mec.biz.dal.page.RewardsRulesQueryInfo;
import com.ym.mec.common.exception.BizException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ym.mec.biz.dal.dao.CourseScheduleRewardsRulesDao;
import com.ym.mec.biz.dal.dao.OrganizationDao;
import com.ym.mec.biz.dal.entity.CourseSchedule.CourseScheduleType;
import com.ym.mec.biz.dal.entity.CourseScheduleRewardsRules;
import com.ym.mec.biz.dal.entity.CourseScheduleRewardsRules.RewardMode;
import com.ym.mec.biz.service.CourseScheduleRewardsRulesService;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.page.QueryInfo;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.json.JsonUtil;
import org.springframework.transaction.annotation.Transactional;

@Service
public class CourseScheduleRewardsRulesServiceImpl extends BaseServiceImpl<Integer, CourseScheduleRewardsRules> implements CourseScheduleRewardsRulesService {

	@Autowired
	private CourseScheduleRewardsRulesDao courseScheduleRewardsDao;

	@Autowired
	private OrganizationDao organizationDao;

	@Override
	public BaseDAO<Integer, CourseScheduleRewardsRules> getDAO() {
		return courseScheduleRewardsDao;
	}

	@Override
	public PageInfo<CourseScheduleRewardsRules> queryPage(QueryInfo queryInfo) {
		PageInfo<CourseScheduleRewardsRules> pageInfo = new PageInfo<CourseScheduleRewardsRules>(queryInfo.getPage(), queryInfo.getRows());
		Map<String, Object> params = new HashMap<String, Object>();
		MapUtil.populateMap(params, queryInfo);

		List<CourseScheduleRewardsRules> dataList = null;
		int count = this.findCount(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = this.getDAO().queryPage(params);
			for (CourseScheduleRewardsRules rules : dataList) {
				rules.setOrganNameList(organizationDao.findByOrganIds(rules.getOrganId()).stream().collect(Collectors.joining("、")));
			}
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	public BigDecimal queryRewardsAmount(Integer organId, CourseScheduleType courseScheduleType, int coursesNum) {

		List<CourseScheduleRewardsRules> CourseScheduleRewardsRulesList = courseScheduleRewardsDao.query(organId, courseScheduleType);

		if (CourseScheduleRewardsRulesList == null || CourseScheduleRewardsRulesList.size() == 0) {
			return new BigDecimal(0);
		}

		CourseScheduleRewardsRules courseScheduleRewardsRules = CourseScheduleRewardsRulesList.get(0);

		String json = courseScheduleRewardsRules.getRewardsRulesJson();

		List<RewardsRules> rewardsRulesList = JsonUtil.parseArray(json, RewardsRules.class);

		Collections.sort(rewardsRulesList);

		RewardsRules rewardsRules = new RewardsRules();

		for (RewardsRules rule : rewardsRulesList) {
			if (rule.min >= coursesNum && rule.max <= coursesNum) {
				rewardsRules = rule;
				break;
			}
		}

		if (courseScheduleRewardsRules.getRewardMode() == RewardMode.TOTAL) {
			return rewardsRules.getAmount();
		} else if (courseScheduleRewardsRules.getRewardMode() == RewardMode.STAIR) {
			BigDecimal amount = new BigDecimal(0);
			for (RewardsRules rule : rewardsRulesList) {
				if (coursesNum <= rule.max) {
					amount = amount.add(new BigDecimal(coursesNum * rule.amount.doubleValue()));
				} else {
					amount = amount.add(new BigDecimal(rule.max * rule.amount.doubleValue()));
					coursesNum = coursesNum - rule.max;
				}
			}

			return amount;
		}

		return rewardsRules.getAmount().multiply(new BigDecimal(coursesNum));
	}

	@Override
	public List<Integer> queryOrganIdList() {
		List<String> list = courseScheduleRewardsDao.queryOrganIdList();

		List<Integer> result = new ArrayList<Integer>();

		for (String organIdStr : list) {
			String[] organIds = organIdStr.split(",");
			for (String s : organIds) {
				if (!result.contains(Integer.parseInt(s))) {
					result.add(Integer.parseInt(s));
				}
			}
		}

		return result;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int add(CourseScheduleRewardsRules courseScheduleRewardsRules) {
		String teacherId = courseScheduleRewardsRules.getTeacherId();
		String vipGroupCategoryIdList = courseScheduleRewardsRules.getVipGroupCategoryIdList();
		String subjectIds = courseScheduleRewardsRules.getSubjectIds();
		if(StringUtils.isEmpty(teacherId) || StringUtils.isEmpty(vipGroupCategoryIdList)){
			throw new BizException("参数校验异常");
		}
		if(StringUtils.isEmpty(courseScheduleRewardsRules.getRewardsRulesJson())){
			throw new BizException("请设置梯度");
		}
		//同一种课程形式，只能有一个老师
		List<CourseScheduleRewardsRules> scheduleRewardsRules = courseScheduleRewardsDao.findByTeacherAndCategory(teacherId,vipGroupCategoryIdList,subjectIds);
		if(scheduleRewardsRules != null && scheduleRewardsRules.size() > 0){
			throw new BizException("重复的数据");
		}
		courseScheduleRewardsDao.insert(courseScheduleRewardsRules);
		return courseScheduleRewardsRules.getId();
	}

	@Override
	public PageInfo<CourseScheduleRewardsRules> queryDetailPage(RewardsRulesQueryInfo queryInfo) {
		PageInfo<CourseScheduleRewardsRules> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
		Map<String, Object> params = new HashMap<>();
		MapUtil.populateMap(params, queryInfo);
		List<CourseScheduleRewardsRules> dataList = null;
		int count = courseScheduleRewardsDao.findDetailPage(params);
		if (count > 0) {
			pageInfo.setTotal(count);
			params.put("offset", pageInfo.getOffset());
			dataList = courseScheduleRewardsDao.queryDetailPage(params);
			List<Integer> rewardsIds = dataList.stream().map(e -> e.getId()).collect(Collectors.toList());
			//获取教师列表
			if(rewardsIds != null && rewardsIds.size() > 0){
				Map<Integer,String> teacherNameMap = MapUtil.convertIntegerMap(courseScheduleRewardsDao.findTeacherNames(rewardsIds));
				Map<Integer,String> vipCategoryNameMap = MapUtil.convertIntegerMap(courseScheduleRewardsDao.findVipCategoryNames(rewardsIds));
				dataList.forEach(e->{
					e.setTeacherNames(teacherNameMap.get(e.getId()));
					e.setVipGroupCategoryNameList(vipCategoryNameMap.get(e.getId()));
				});
			}
		}
		if (count == 0) {
			dataList = new ArrayList<>();
		}
		pageInfo.setRows(dataList);
		return pageInfo;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public int updateDetail(CourseScheduleRewardsRules courseScheduleRewardsRules) {
		String teacherId = courseScheduleRewardsRules.getTeacherId();
		String vipGroupCategoryIdList = courseScheduleRewardsRules.getVipGroupCategoryIdList();
		String subjectIds = courseScheduleRewardsRules.getSubjectIds();
		if(StringUtils.isEmpty(teacherId) || StringUtils.isEmpty(vipGroupCategoryIdList)){
			throw new BizException("参数校验异常");
		}
		if(StringUtils.isEmpty(courseScheduleRewardsRules.getRewardsRulesJson())){
			throw new BizException("请设置梯度");
		}
		if(courseScheduleRewardsRules.getId() == null){
			throw new BizException("参数校验异常");
		}
		//同一种课程形式，只能有一个老师
		List<CourseScheduleRewardsRules> scheduleRewardsRules = courseScheduleRewardsDao.findByTeacherAndCategory(teacherId,vipGroupCategoryIdList,subjectIds);
		if(scheduleRewardsRules.size() > 1){
			throw new BizException("重复的数据");
		}
		if(scheduleRewardsRules.size() == 1){
			CourseScheduleRewardsRules rewardsRules = scheduleRewardsRules.get(0);
			if(!rewardsRules.getId().equals(courseScheduleRewardsRules.getId())){
				throw new BizException("重复的数据");
			}
		}
		courseScheduleRewardsRules.setUpdateTime(new Date());
		courseScheduleRewardsDao.update(courseScheduleRewardsRules);
		return courseScheduleRewardsRules.getId();
	}

	@Override
	public List<TaskRewardsRulesDto> queryVipGroupTeacherClassTimesByMonth(String firstDayOfMonth, String lastDayOfMonth) {
		return courseScheduleRewardsDao.queryVipGroupTeacherClassTimesByMonth(firstDayOfMonth,lastDayOfMonth);
	}

	@Override
	public List<CourseScheduleRewardsRules> findByIds(List<Integer> activeIds) {
		return courseScheduleRewardsDao.findByIds(activeIds);
	}

	class RewardsRules implements Comparable<RewardsRules> {

		private int min;

		private int max;

		private BigDecimal amount = new BigDecimal(0);

		public int getMin() {
			return min;
		}

		public void setMin(int min) {
			this.min = min;
		}

		public int getMax() {
			return max;
		}

		public void setMax(int max) {
			this.max = max;
		}

		public BigDecimal getAmount() {
			return amount;
		}

		public void setAmount(BigDecimal amount) {
			this.amount = amount;
		}

		@Override
		public int compareTo(RewardsRules rules) {
			if (this.min > rules.min) {
				return 1;
			}
			return -1;
		}
	}
}