package com.ssj.service.kmt.kmt.service.impl;


import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSONObject;
import com.ssj.bean.kmt.kmt.domain.KmtArrangeAllot;
import com.ssj.bean.kmt.kmt.domain.KmtArrangeDetail;
import com.ssj.bean.weixin.libmy.domain.TbLibManager;
import com.ssj.dao.kmt.kmt.dao.KmtArrangeDetailDao;
import com.ssj.dao.kmt.kmt.dao.KmtArrangeQueryDao;
import com.ssj.framework.basic.utils.DateHelper;
import com.ssj.framework.core.common.service.BaseServiceImpl;
import com.ssj.framework.core.util.RedisUtil;
import com.ssj.service.kmt.arrange.dto.*;
import com.ssj.service.kmt.arrange.service.KmtArrangeAllotService;
import com.ssj.service.kmt.arrange.service.KmtArrangeDetailService;
import com.ssj.service.weixin.library.service.IBookManagerService;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;

import static java.math.BigDecimal.ROUND_HALF_DOWN;


	
@Transactional
@Service(version ="1.0")
public class KmtArrangeDetailServiceImpl extends BaseServiceImpl<KmtArrangeDetail, String> implements KmtArrangeDetailService {
	
	protected Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Autowired
	private KmtArrangeDetailDao dao;
	
	@Autowired
	private KmtArrangeQueryDao queryDao;
	
	@Autowired
	private IBookManagerService managerService;
	
	@Autowired
	private KmtArrangeAllotService kmtArrangeAllotService;
	
	@Autowired
	private RedisUtil redisUtil;
	
	
	
	@Override
	public PagingAndSortingRepository<KmtArrangeDetail, String> getDao() {
		return dao;
	}

	@Override
	public List<KmtArrangeDetail> findKmtArrangeDetailByCurMonth(String type,String subject) {
		return dao.findKmtArrangeDetailByCurMonth(type, subject);
	}

	@Override
	public List<KmtArrangeDetail> findKmtArrangeDetailByMonth(String month,String type, String subject) {
		if(StringUtils.isNotEmpty(month)){
			return dao.findKmtArrangeDetailByMonth(month,type, subject);
		}else{
			return dao.findKmtArrangeDetailByCurMonth(type, subject);
		}
	}


	@Override
	public ArrangeCalendarDto findCalendarList(String month,String type, String subject) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		ArrangeCalendarDto arrangeCalendarDto=new ArrangeCalendarDto();
		arrangeCalendarDto.setSubject(subject);
		arrangeCalendarDto.setType(type);
		arrangeCalendarDto.setIsNextMonth(calendar.get(Calendar.DAY_OF_MONTH)>=25?1:0);

		List<KmtArrangeDetail> kmtArrangeDetails=null;
		if(StringUtils.isNotEmpty(month)){
			kmtArrangeDetails=this.findKmtArrangeDetailByMonth(month+"-01",type,subject);
			Date date=DateHelper.parseDate(month, "yyyy-MM");
			Calendar cal=Calendar.getInstance();  
		    cal.setTime(date); 
			arrangeCalendarDto.setMonth(cal.get(Calendar.MONTH)+1);
		}else{
			kmtArrangeDetails=this.findKmtArrangeDetailByCurMonth(type,subject);
			arrangeCalendarDto.setMonth(Calendar.getInstance().get(Calendar.MONTH)+1);
		}
		for (KmtArrangeDetail kmtArrangeDetail : kmtArrangeDetails) {
			arrangeCalendarDto.addArrangeDetailDto(kmtArrangeDetail);
		}
		return arrangeCalendarDto;
	}
	
	
	@Override
	public ArrangeTeacherDto findHaveTeacherList(String parentTeacherId,String id, String teacherName) {
		DecimalFormat df = new DecimalFormat("#0.00");
		ArrangeTeacherDto arrangeTeacherDto=new ArrangeTeacherDto();
		KmtArrangeDetail kmtArrangeDetail=this.getById(id);
		Map<String,String> dutyRatioMap=new LinkedHashMap<String, String>();
		if(kmtArrangeDetail!=null){
			ArrangeIntervalDto arrangeDetail=new ArrangeIntervalDto();
			arrangeDetail.setId(id);
			arrangeDetail.setArrangeDate(DateHelper.format(kmtArrangeDetail.getArrangeDate(), "yyyy-MM-dd"));
			arrangeDetail.setStartInterval(kmtArrangeDetail.getStartInterval());
			arrangeDetail.setEndInterval(kmtArrangeDetail.getEndInterval());
			arrangeDetail.setIsOpen(kmtArrangeDetail.getIsOpen());
			arrangeDetail.setMaxNum(kmtArrangeDetail.getMaxNum());
			arrangeDetail.setMiniNum(kmtArrangeDetail.getMiniNum());
			arrangeDetail.setHaveNum(kmtArrangeDetail.getHaveNum());
			if(DateHelper.dateQualsByMonth(kmtArrangeDetail.getArrangeDate(),new Date())
					|| DateHelper.isLastDayOfMonth(DateHelper.theMonthFirstDate(kmtArrangeDetail.getArrangeDate()),new Date())){
				arrangeDetail.setIsAdd(1);
			}else{
				arrangeDetail.setIsAdd(0);
			}
			arrangeTeacherDto.setArrangeDetail(arrangeDetail);
			
			List<Map<String,Object>> mapList=queryDao.findHaveTeacherList(parentTeacherId, id, teacherName);
			for (Map<String, Object> map : mapList) {
				ArrangeTeacherDetailDto arrangeTeacherDetailDto=new ArrangeTeacherDetailDto();
				arrangeTeacherDetailDto.setTeacherId(ObjectUtils.defaultIfNull(map.getOrDefault("teacher_id", ""), "").toString());
				arrangeTeacherDetailDto.setTeacherName(ObjectUtils.defaultIfNull(map.getOrDefault("name", ""), "").toString());
				arrangeTeacherDetailDto.setPhoto(ObjectUtils.defaultIfNull(map.getOrDefault("t_photo", ""), "").toString());
				arrangeTeacherDetailDto.setHaveCount(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("fullcount", "0"), "0").toString()));
				arrangeTeacherDetailDto.setSubject(kmtArrangeDetail.getSubject());
				arrangeTeacherDetailDto.setAttendanceRatio(
						Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("count", "0"), "0").toString()) >0
						? df.format(new BigDecimal(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("attend_sum", "0"), "0").toString()))
						    .divide(new BigDecimal(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("count", "0"), "0").toString())),10,ROUND_HALF_DOWN).multiply(new BigDecimal(100)))
						: "0.00");
				if(StringUtils.isNotEmpty(parentTeacherId)){
					arrangeTeacherDetailDto.setIsEdit(
							(ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString())
							.equals(parentTeacherId) 
							? ((DateHelper.dateQualsByMonth(kmtArrangeDetail.getArrangeDate(),new Date())
									|| DateHelper.isLastDayOfMonth(DateHelper.theMonthFirstDate(kmtArrangeDetail.getArrangeDate()),new Date()))) ? 1 : 0 : 0);
				}else{
					//判断是否为当月，或上一个月的最后一天，其它时段不能移除
					if(DateHelper.dateQualsByMonth(kmtArrangeDetail.getArrangeDate(),new Date())
							|| DateHelper.isLastDayOfMonth(DateHelper.theMonthFirstDate(kmtArrangeDetail.getArrangeDate()),new Date())){
							arrangeTeacherDetailDto.setIsEdit(1);
					}else{
						arrangeTeacherDetailDto.setIsEdit(0);
					}
				}
				
				//实时小组在岗率：实时排班时长达到 30 个时段的人数／小组总人数
				if(dutyRatioMap.containsKey((ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString()))){
					arrangeTeacherDetailDto.setDutyRatio(dutyRatioMap.get((ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString())));
				}else{
					List<Map<String, Object>> GTList=queryDao.findGTTeacherByMonthList(ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString(), new Date());
					if(GTList!=null && GTList.size()>0){
						List<TbLibManager> list= managerService.findByParentId(ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString());
						if(list!=null && list.size()>0){
							arrangeTeacherDetailDto.setDutyRatio(df.format(new BigDecimal(GTList.size())
							.divide(new BigDecimal(list.size()),10,ROUND_HALF_DOWN).multiply(new BigDecimal(100))));
							dutyRatioMap.put(ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString(), arrangeTeacherDetailDto.getDutyRatio());
						}
					}
				}
				arrangeTeacherDto.getList().add(arrangeTeacherDetailDto);
			}
		}
		return arrangeTeacherDto;
	}
	


	@Override
	public ArrangeTeacherDto findNoHaveTeacherList(String parentTeacherId,String id, String teacherName) {
		DecimalFormat df = new DecimalFormat("#0.00");
		ArrangeTeacherDto arrangeTeacherDto=new ArrangeTeacherDto();
		KmtArrangeDetail kmtArrangeDetail=this.getById(id);
		Map<String,String> dutyRatioMap=new LinkedHashMap<String, String>();
		if(kmtArrangeDetail!=null){
			ArrangeIntervalDto arrangeDetail=new ArrangeIntervalDto();
			arrangeDetail.setId(id);
			arrangeDetail.setArrangeDate(DateHelper.format(kmtArrangeDetail.getArrangeDate(), "yyyy-MM-dd"));
			arrangeDetail.setStartInterval(kmtArrangeDetail.getStartInterval());
			arrangeDetail.setEndInterval(kmtArrangeDetail.getEndInterval());
			arrangeDetail.setIsOpen(kmtArrangeDetail.getIsOpen());
			arrangeDetail.setMaxNum(kmtArrangeDetail.getMaxNum());
			arrangeDetail.setMiniNum(kmtArrangeDetail.getMiniNum());
			arrangeDetail.setHaveNum(kmtArrangeDetail.getHaveNum());
			arrangeTeacherDto.setArrangeDetail(arrangeDetail);
			
			String subject=kmtArrangeDetail.getSubject();
			Integer type=kmtArrangeDetail.getType();
			List<String> noAddTeacherIds=new ArrayList<String>();

			//查出小组的所有老师，type and subject
			List<String> tbLibManagers=managerService.findByParentIdAndTypeAndCourseName(parentTeacherId,type,subject,teacherName);
			//查出这个时段已经添加的老师Id
			List<String> kmtArrangeAllots=kmtArrangeAllotService.findKmtArrangeAllotByArrangeDetailId(id);
			for (String teacherId : tbLibManagers) {
				if(!kmtArrangeAllots.contains(teacherId)){
					noAddTeacherIds.add(teacherId);
				}
			}
			if(noAddTeacherIds.size()>0){
				List<Map<String,Object>> mapList=queryDao.findNoHaveTeacherList(noAddTeacherIds, DateHelper.parseDate(arrangeDetail.getArrangeDate(), "yyyy-MM-dd"));
				for (Map<String, Object> map : mapList) {
					ArrangeTeacherDetailDto arrangeTeacherDetailDto=new ArrangeTeacherDetailDto();
					arrangeTeacherDetailDto.setTeacherId(ObjectUtils.defaultIfNull(map.getOrDefault("teacher_id", ""), "").toString());
					arrangeTeacherDetailDto.setTeacherName(ObjectUtils.defaultIfNull(map.getOrDefault("name", ""), "").toString());
					arrangeTeacherDetailDto.setPhoto(ObjectUtils.defaultIfNull(map.getOrDefault("t_photo", ""), "").toString());
					arrangeTeacherDetailDto.setHaveCount(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("fullcount", "0"), "0").toString()));
					arrangeTeacherDetailDto.setSubject(kmtArrangeDetail.getSubject());
					arrangeTeacherDetailDto.setAttendanceRatio(
							Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("count", "0"), "0").toString())>0 
								? df.format(new BigDecimal(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("attend_sum", "0"), "0").toString()))
								    .divide(new BigDecimal(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("count", "0"), "0").toString())),10,ROUND_HALF_DOWN).multiply(new BigDecimal(100)))
							: "0.00");
					
					//实时小组在岗率：实时排班时长达到 30 个时段的人数／小组总人数
					if(dutyRatioMap.containsKey((ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString()))){
						arrangeTeacherDetailDto.setDutyRatio(dutyRatioMap.get((ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString())));
					}else{
						List<Map<String, Object>> GTList=queryDao.findGTTeacherByMonthList(ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString(), new Date());
						if(GTList!=null && GTList.size()>0){
							List<TbLibManager> list= managerService.findByParentId(ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString());
							if(list!=null && list.size()>0){
								arrangeTeacherDetailDto.setDutyRatio(
										df.format(new BigDecimal(GTList.size())
										.divide(new BigDecimal(list.size()),10,ROUND_HALF_DOWN).multiply(new BigDecimal(100))));
								dutyRatioMap.put(ObjectUtils.defaultIfNull(map.getOrDefault("parent_id", ""), "").toString(), arrangeTeacherDetailDto.getDutyRatio());
							}
						}
					}
					arrangeTeacherDto.getList().add(arrangeTeacherDetailDto);
				}
			}
		}	
		return arrangeTeacherDto;
	}


	@Override
	public boolean deleteArrangeByTeacher(String id, String teacherId) {
		try {
			synchronized(this){
				kmtArrangeAllotService.updateKmtArrangeAllotToStatus(id, teacherId, 0);
				Integer count=kmtArrangeAllotService.countKmtArrangeAllotByArrangeDetailId(id);
				dao.updateKmtArrangeDetailToHaveNum(id, count);
			}
		} catch (Exception e) {
			return false;
		}
		return true;
	}


	/**
	 * reqCode
	 * 1：成功
	 * 2：必须提前于排班时段前 4 个小时进行
	 * 3：此时段添加老师量已超出饱和量
	 * 4：此时段数据不存在
	 * 500：异常
	 * 
	 */
	@Override
	public Integer addArrangeByTeacher(String id, List<String> teacherIds) {
		Integer reqCode=1;
		try {
			synchronized(this){
				List<KmtArrangeAllot> kmtArrangeAllots=new ArrayList<KmtArrangeAllot>();
				KmtArrangeDetail kmtArrangeDetail=this.getById(id);
				if(kmtArrangeDetail!=null){
					
					String kmtDetailDate=DateHelper.format(kmtArrangeDetail.getArrangeDate(), "yyyy-MM-dd")+" "+kmtArrangeDetail.getStartInterval();
					Long s = (DateHelper.parseDate(kmtDetailDate, "yyyy-MM-dd HH:mm").getTime()-System.currentTimeMillis()) / (1000 * 60);
					if(240 >=s){
						logger.error("{}：排班必须提前于排班时段前 4 个小时进行",kmtArrangeDetail.getId());
						reqCode=2;
						return reqCode;
					}
//					if(kmtArrangeDetail.getMaxNum()<(kmtArrangeDetail.getHaveNum()+teacherIds.size())){
//						logger.error("{}：此时段添加老师量已超出饱和量",kmtArrangeDetail.getId());
//						reqCode=3;
//						return reqCode;
//					}
					for (String teacherId : teacherIds) {
						KmtArrangeAllot kmtArrangeAllot=new KmtArrangeAllot();
						kmtArrangeAllot.setArrangeDate(kmtArrangeDetail.getArrangeDate());
						kmtArrangeAllot.setArrangeDetailId(id);
						kmtArrangeAllot.setStatus(1);
						kmtArrangeAllot.setAttendType(0);
						kmtArrangeAllot.setCreateTime(new Date());
						kmtArrangeAllot.setTeacherId(teacherId);
						kmtArrangeAllots.add(kmtArrangeAllot);
					}
					kmtArrangeAllotService.save(kmtArrangeAllots);
					Integer count=kmtArrangeAllotService.countKmtArrangeAllotByArrangeDetailId(id);
					dao.updateKmtArrangeDetailToHaveNum(id, count);
				}else{
					reqCode=4;
				}
			}
		} catch (Exception e) {
			logger.error("addArrangeByTeacher添加老师异常:{}",e.getMessage());
			reqCode=500;
		}
		return reqCode;
	}


	@Override
	public ArrangeTeamTeacherDto findTeamTeacherList(String parentTeacherId,String type,String id,String teacherName,Pageable pageable) {
		ArrangeTeamTeacherDto arrangeTeamTeacherDto=new ArrangeTeamTeacherDto();
		arrangeTeamTeacherDto.setDutyRatio("0.00");
		
		DecimalFormat df = new DecimalFormat("#0.00");
		String arrangeDate=null;
		String tempId=null;
		if(StringUtils.isNotEmpty(id)){
			KmtArrangeDetail kmtArrangeDetail=this.getById(id);
			if(kmtArrangeDetail!=null){
				arrangeDate=DateHelper.format(kmtArrangeDetail.getArrangeDate(),"yyyy-MM-dd");
				tempId=kmtArrangeDetail.getArrangeTemplateId();
			}
		}
		Page<Map<String, Object>> page=queryDao.findTeamTeacherList(parentTeacherId, type, tempId, arrangeDate, teacherName, pageable);
		List<Map<String, Object>> mapList=page.getContent();
		for (Map<String, Object> map : mapList) {
			ArrangeTeacherDetailDto arrangeTeacherDetailDto=new ArrangeTeacherDetailDto();
			arrangeTeacherDetailDto.setTeacherId(ObjectUtils.defaultIfNull(map.getOrDefault("teacher_id", ""), "").toString());
			arrangeTeacherDetailDto.setTeacherName(ObjectUtils.defaultIfNull(map.getOrDefault("name", ""), "").toString());
			arrangeTeacherDetailDto.setPhoto(ObjectUtils.defaultIfNull(map.getOrDefault("t_photo", ""), "").toString());
			arrangeTeacherDetailDto.setHaveCount(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("fullcount", "0"), "0").toString()));
			arrangeTeacherDetailDto.setSubject(ObjectUtils.defaultIfNull(map.getOrDefault("course_name", ""), "").toString());
			arrangeTeacherDetailDto.setDutyRatio("0.00");
			arrangeTeacherDetailDto.setAttendanceRatio(
					Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("count", "0"), "0").toString())>0 
					? df.format(new BigDecimal(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("attend_sum", "0"), "0").toString()))
						.divide(new BigDecimal(Integer.parseInt(ObjectUtils.defaultIfNull(map.getOrDefault("count", "0"), "0").toString())),10,ROUND_HALF_DOWN).multiply(new BigDecimal(100)))
					: "0.00");
			
			arrangeTeamTeacherDto.getList().add(arrangeTeacherDetailDto);
		}
		arrangeTeamTeacherDto.setTotalElements(page.getTotalElements());
		arrangeTeamTeacherDto.setTotalPages(page.getTotalPages());
		
		//实时小组在岗率：实时排班时长达到 30 个时段的人数／小组总人数
		List<Map<String, Object>> GTList=queryDao.findGTTeacherByMonthList(parentTeacherId, new Date());
		if(GTList!=null && GTList.size()>0){
			List<TbLibManager> list= managerService.findByParentId(parentTeacherId);
			if(list!=null && list.size()>0){
				arrangeTeamTeacherDto.setDutyRatio(
						df.format(new BigDecimal(GTList.size())
						.divide(new BigDecimal(list.size()),10,ROUND_HALF_DOWN).multiply(new BigDecimal(100)))
						);
			}
		}
		return arrangeTeamTeacherDto;
	}
	

	
	@Override
	public List<KmtArrangeDetail> findKmtArrangeDetailByMonth(String month) {
		return dao.findKmtArrangeDetailByMonth(month);
	}

	@Override
	public void pushKmtArrangeDetailByMiniNum() {
		boolean isPush=false;
		List<KmtArrangeDetail> kmtArrangeDetails=this.findKmtArrangeDetailByMonth(DateHelper.format(new Date(), "yyyy-MM-dd"));
		for (KmtArrangeDetail kmtArrangeDetail : kmtArrangeDetails) {
			if(kmtArrangeDetail.getHaveNum()<kmtArrangeDetail.getMiniNum()){
				isPush=true;
				break;
			}
		}
		//发送提醒给校区管理员
		//发送提醒给超级管理员
		if(isPush){
			
		}
	}

	
	@Override
	public void initKmtArrangeDetailByRedis(String month) {
		List<KmtArrangeDetail> kmtArrangeDetails=this.findKmtArrangeDetailByMonth(month);
		for (KmtArrangeDetail kmtArrangeDetail : kmtArrangeDetails) {
			redisUtil.set(kmtArrangeDetail.getId(), JSONObject.toJSONString(kmtArrangeDetail));
		}
	}


	@Override
	public boolean updateKmtArrangeDetailByRedisKey(String id, int haveNum) {
		synchronized(this){
			if(redisUtil.exists(id)){
				String jsonObj=redisUtil.get(id);
				KmtArrangeDetail kmtArrangeDetail=JSONObject.parseObject(jsonObj, KmtArrangeDetail.class);
				if(kmtArrangeDetail!=null){
					if(kmtArrangeDetail.getMaxNum()>=kmtArrangeDetail.getHaveNum()+haveNum){
						kmtArrangeDetail.setHaveNum(kmtArrangeDetail.getHaveNum()+haveNum);
						redisUtil.set(kmtArrangeDetail.getId(), JSONObject.toJSONString(kmtArrangeDetail));
						return true;
					}
				}
			}else{
				KmtArrangeDetail kmtArrangeDetail=this.getById(id);
				if(kmtArrangeDetail!=null){
					if(kmtArrangeDetail.getMaxNum()>=kmtArrangeDetail.getHaveNum()+haveNum){
						kmtArrangeDetail.setHaveNum(kmtArrangeDetail.getHaveNum()+haveNum);
						redisUtil.set(kmtArrangeDetail.getId(), JSONObject.toJSONString(kmtArrangeDetail));
						return true;
					}
				}
			}
		}
		return false;
	}


}
