package cn.timer.api.controller.kqgl.atttimer;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import cn.timer.api.bean.kqgl.AttendanceWeeklySch;
import cn.timer.api.bean.kqgl.PunchCardDetails;
import cn.timer.api.bean.kqgl.Schedule;
import cn.timer.api.bean.kqmk.KqglAssoBcsz;
import cn.timer.api.bean.kqmk.KqglAssoDkjl;
import cn.timer.api.bean.kqmk.KqglAssoDkmx;
import cn.timer.api.bean.kqmk.KqglAssoMonthPunchSummary;
import cn.timer.api.bean.kqmk.KqglAssoPbmx;
import cn.timer.api.bean.kqmk.KqglAssoTeshu;
import cn.timer.api.bean.kqmk.KqglAssoZhoupaiban;
import cn.timer.api.bean.kqmk.KqglMainKqz;
import cn.timer.api.bean.kqmk.KqglTaskTiming;
import cn.timer.api.bean.qyzx.QyzxEntInfoM;
import cn.timer.api.controller.kqgl.ClockInTool;
import cn.timer.api.dao.kqgl.AttendanceWeeklySchMapper;
import cn.timer.api.dao.kqgl.PunchCardDetailsMapper;
import cn.timer.api.dao.kqgl.ScheduleMapper;
import cn.timer.api.dao.kqmk.KqglAssoDkjlMapper;
import cn.timer.api.dao.kqmk.KqglAssoLeaveBalanceMapper;
import cn.timer.api.dao.kqmk.KqglAssoTeshuMapper;
import cn.timer.api.dao.kqmk.KqglMainKqzMapper;
import cn.timer.api.dao.qyzx.QyzxEntInfoMMapper;
import cn.timer.api.dto.kqmk.AdditionalDto;
import cn.timer.api.utils.DateUtil;

/**
 * @author lal
 *
 */
@Component
@Lazy
public class AttendanceTaskTiming implements SchedulingConfigurer {

	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
	static String tablename = null;
	
	@Autowired
	private KqglMainKqzMapper kqglmainkqzmapper;
	@Autowired
	private QyzxEntInfoMMapper qyzxentinfommapper;
	@Autowired
	private KqglAssoLeaveBalanceMapper kqglassoleavebalancemapper;
	@Autowired
	private KqglAssoTeshuMapper kqglassoteshumapper;
	@Autowired
	private KqglAssoDkjlMapper kqglassodkjlmapper;
	@Autowired
	private PunchCardDetailsMapper punchcarddetailsmapper;
	@Autowired
	private AttendanceWeeklySchMapper attendanceweeklyschmapper;
	@Autowired
	private ScheduleMapper schedulemapper;

	
	SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
	SimpleDateFormat sdf2 = new SimpleDateFormat("EEE");
	
	/**
	 *	数据库动态更改定时配置(attendance_socks)
	 */
	@Override
	public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
		taskRegistrar.addTriggerTask(() -> {
			// 任务逻辑
			try {
				tablename = AttendanceTask();
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}, triggerContext -> {
			CronTrigger cron = new CronTrigger(AttendanceUtil.getCron(tablename)); // cron配置
			return cron.nextExecutionTime(triggerContext); // 下次执行任务的时间
		});
	}
	
	

	/**
	 * @return
	 * @throws ParseException 
	 */
//	@Scheduled(cron = "0/5 * * * * ?") // 测试:5秒执行一次
	@SuppressWarnings("unused")
	public  String AttendanceTask() throws ParseException {
		boolean implement = false;
		KqglTaskTiming sock = KqglTaskTiming.builder().build().selectOne(new QueryWrapper<KqglTaskTiming>().lambda().eq(KqglTaskTiming::getTask, "AttendanceTask"));
		if(sock == null) {
			KqglTaskTiming.builder().task("AttendanceTask").executionStatus(1).lastExecutionTime(new Date().getTime()).build().insert();
			implement = true;
		}else {
			if(sock.getExecutionStatus() == 0) {
				KqglTaskTiming.builder().task("AttendanceTask").id(sock.getId()).executionStatus(1).lastExecutionTime(new Date().getTime()).build().updateById();
				implement = true;
			}
		}
		//逻辑
		if(false) {
			
			System.err.println("当前时间:" + dateFormat.format(new Date()));
			
			Calendar c = Calendar.getInstance();    
			c.add(Calendar.MONTH, 0);
			c.set(Calendar.DAY_OF_MONTH,1);//设置为1号,当前日期既为本月第一天 
			Long startDate = DateUtil.getStartTime(0,DateUtil.getStringTime(sdf1.format(c.getTime()),"yyyy-MM-dd")).getTime();
			//获取当前月最后一天
			Calendar ca = Calendar.getInstance();    
			ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));  
			Long endDate = DateUtil.getnowEndTime(23,DateUtil.getStringTime(sdf1.format(ca.getTime()),"yyyy-MM-dd")).getTime();
			
			List<QyzxEntInfoM> orgcodelist = qyzxentinfommapper.selectList(new QueryWrapper<QyzxEntInfoM>());//系统中的所有公司  所有未到期的公司
			
			String str = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString();//
			String[] range=ClockInTool.listToString(ClockInTool.getDays(sdf1.format(c.getTime()),str)).split(";");//目前为止所有日期
			
			for(int t = 0;t<orgcodelist.size();t++){
				int org_code = orgcodelist.get(t).getId();//企业组织代码
				List<AdditionalDto> userlist = kqglassoleavebalancemapper.selectAdditionalList(org_code);
				for(AdditionalDto user : userlist) {
	/*****/			for(String num : range) {//遍历目前为止所有日期
		
						Long startDatestop = DateUtil.getStartTime(0,DateUtil.getStringTime(num,"yyyy-MM-dd")).getTime();
						Long endDatestop = DateUtil.getnowEndTime(23,DateUtil.getStringTime(num,"yyyy-MM-dd")).getTime();
		
						//考勤组信息
						KqglMainKqz attgro = kqglmainkqzmapper.getAttendanceGroupInformationByUserid(user.getEmpnum(),org_code); 
						//目前为止打卡记录
						List<PunchCardDetails> attendance = punchcarddetailsmapper.selectAttendanceDays(Integer.valueOf(user.getEmpnum()), startDate, new Date().getTime());
						int dkjl = 0;//目前为止打卡次数
						if(attendance.size() > 0) { dkjl = attendance.size(); }
						//具体打卡时间入汇总表(打卡成功才会录入汇总表)
						 KqglAssoMonthPunchSummary isyessum = KqglAssoMonthPunchSummary.builder().build().selectOne(new QueryWrapper<KqglAssoMonthPunchSummary>().lambda()
								 .eq(KqglAssoMonthPunchSummary::getNum, user.getEmpnum()).eq(KqglAssoMonthPunchSummary::getOrgCode, org_code));
							int year = Calendar.getInstance().get(Calendar.YEAR);
							int month = Calendar.getInstance().get(Calendar.MONTH) + 1;
							if(attgro != null){//该员工是否加入到考勤组  排班方式 1:固定排班;2:自由排班;3:自由工时         计算出应出勤,实际出勤,休息天数
								KqglAssoBcsz shif = KqglAssoBcsz.builder().build();
								//休息天数,应出勤天数,实际出勤
								double daysOff = 0,daysOnDuty = 0;//,actualAttDays = 0;
								int zjgzts = 0;//目前为止应该出勤的天数
								if(attgro.getPbfs() == 1){	//固定排班
									int several = Integer.valueOf(ClockInTool.dateToWeek(str));//
									KqglAssoTeshu tesu = KqglAssoTeshu.builder().build().selectOne(new QueryWrapper<KqglAssoTeshu>().lambda().eq(KqglAssoTeshu::getKqzid, attgro.getId()).eq(KqglAssoTeshu::getTsrq, str));
									if(tesu == null) {
										//获取该员工最新班次
										KqglAssoZhoupaiban gudingpb = KqglAssoZhoupaiban.builder().build().selectOne(new QueryWrapper<KqglAssoZhoupaiban>().lambda().eq(KqglAssoZhoupaiban::getKqzid, attgro.getId())
												.eq(KqglAssoZhoupaiban::getType, several));
										shif = shif.selectOne(new QueryWrapper<KqglAssoBcsz>().lambda().eq(KqglAssoBcsz::getId, gudingpb.getBcid()));
									}else {
										shif = shif.selectOne(new QueryWrapper<KqglAssoBcsz>().lambda().eq(KqglAssoBcsz::getId, tesu.getBcid()));
									}
									
									//获取该员工最新班次
									KqglAssoZhoupaiban gudingpb = KqglAssoZhoupaiban.builder().build().selectOne(new QueryWrapper<KqglAssoZhoupaiban>().lambda().eq(KqglAssoZhoupaiban::getKqzid, attgro.getId())
											.eq(KqglAssoZhoupaiban::getType, several));
									shif = shif.selectOne(new QueryWrapper<KqglAssoBcsz>().lambda().eq(KqglAssoBcsz::getId, gudingpb.getBcid()));
									
									List<KqglAssoTeshu> bxdklist = kqglassoteshumapper.ShouldSpecialDatessetByKqzid(attgro.getId(), month,1);//当前月     必须打卡日期
									int bxdk = bxdklist.size();
									String[] bxdkss = new String[bxdk];
									int b = 0;
									for(KqglAssoTeshu bxd : bxdklist) {
										bxdkss[b] = bxd.getTsrq();
										b++;
									}
									List<KqglAssoTeshu> wxdk = kqglassoteshumapper.ShouldSpecialDatessetByKqzid(attgro.getId(), month,2);//当前月     无需打卡日期
									String[] appmaps= new String[wxdk.size()];
									int d1 = 0;
									for(KqglAssoTeshu spe:wxdk){
										appmaps[d1] = spe.getTsrq();
										d1++;
									}
									List<AttendanceWeeklySch> atwek = attendanceweeklyschmapper.selectAttendanceMadeByUserid(Integer.valueOf(user.getEmpnum()));
									String[] week= new String[atwek.size()];
									String[] needfig = new String[atwek.size()];
									int e = 0;
									for(AttendanceWeeklySch awek : atwek){
										week[e] = awek.getWekmc();
										needfig[e] = String.valueOf(awek.getType());//获取设置的应打卡周几
										e++;
									}
									String yemo = year + "-" + month;
									sdf1.setLenient(false);
									int y = 0,q = 0;
									 for(int i = 1; i <= ClockInTool.getDaysByYearMonth(year,month); i++){
											Date date1 = sdf1.parse(yemo + "-" + i);
											for(int u=0;u<week.length;u++){
												if(sdf2.format(date1).equals(week[u])){
													q++;
													y++;
													if(Arrays.asList(appmaps).contains(String.valueOf(sdf1.format(date1)))){
														y = y-1;
													}
												}
											}
									 }
									 int xiuxi = ClockInTool.getDaysByYearMonth(year,month) - q - bxdk + wxdk.size();
									 daysOff = xiuxi;
									 daysOnDuty = y+bxdk;
									 
//									 String[] range=ClockInTool.listToString(ClockInTool.getDays(sdf1.format(c.getTime()),str)).split(";");//目前为止所有日期
//									 int zjgzts = 0;//目前为止应该出勤的天数
									//目前为止应出勤天数
									if(Arrays.binarySearch(needfig, Integer.valueOf(ClockInTool.dateToWeek(num))) >= 0) {//对比排班应打卡时间
										zjgzts++;
									}
									if(Arrays.binarySearch(bxdkss, num) >= 0) {//检查是否存在 必须打卡名单中
										zjgzts++;
									}
									if(Arrays.binarySearch(appmaps, num) >= 0) {//检查是否存在 无需打卡名单中
										zjgzts = zjgzts - 1;
									}
								}else if(attgro.getPbfs() == 2){	//自由排班
									KqglAssoPbmx pbmxx = KqglAssoPbmx.builder().build().selectOne(new QueryWrapper<KqglAssoPbmx>().lambda().eq(KqglAssoPbmx::getUserid, user.getEmpnum()).eq(KqglAssoPbmx::getData, str).eq(KqglAssoPbmx::getKqzid, attgro.getId()));
									shif = shif.selectOne(new QueryWrapper<KqglAssoBcsz>().lambda().eq(KqglAssoBcsz::getId, pbmxx.getBcid()));
									List<Schedule> ycqs = schedulemapper.getAttendanceShouldList(Integer.valueOf(user.getEmpnum()),startDate,endDate);
									int xiuxi = 0,shangban = 0,z=0;
									String[] ziyoupb = new String[ycqs.size()];
									for(Schedule sc : ycqs){
										ziyoupb[z] = String.valueOf(sc.getData());
										z++;
										if(sc.getBcid().equals(0)){
											xiuxi++;
										}else{
											shangban++;
										}
									}
									daysOff = xiuxi;
									daysOnDuty = shangban;
									//目前为止应出勤天数
									if(Arrays.binarySearch(ziyoupb, num) >= 0) {
										KqglAssoPbmx pbx = KqglAssoPbmx.builder().build().selectOne(new QueryWrapper<KqglAssoPbmx>().lambda().eq(KqglAssoPbmx::getUserid, user.getEmpnum()).eq(KqglAssoPbmx::getData, num).eq(KqglAssoPbmx::getKqzid, attgro.getId()));
										if(pbx!=null && pbx.getBcid()!=0) {
											zjgzts++;
										}
									}
								}else{
									List<AttendanceWeeklySch> atwek = attendanceweeklyschmapper.selectAttendanceMadeByUserid(Integer.valueOf(user.getEmpnum()));
									String[] week= new String[atwek.size()];
									int e = 0;
									String[] ziyoupb = new String[atwek.size()];
									for(AttendanceWeeklySch awek : atwek){
										week[e] = awek.getWekmc();
										ziyoupb[e] = String.valueOf(awek.getType());
										e++;
									}
									String yemo = year + "-" + month;
									sdf1.setLenient(false);
									int y = 0;
									 for(int i = 1; i <= ClockInTool.getDaysByYearMonth(year,month); i++){
											Date date1 = sdf1.parse(yemo + "-" + i);
											for(int u=0;u<week.length;u++){
												if(sdf2.format(date1).equals(week[u])){
													y++;
												}
											}
									 }
									 int xiuxi = ClockInTool.getDaysByYearMonth(year,month) - y;
									 daysOff = xiuxi;
								     daysOnDuty = y;
								     //目前为止应出勤天数
							    	 if(Arrays.binarySearch(ziyoupb, Integer.valueOf(ClockInTool.dateToWeek(num))) >= 0) {//对比排班应打卡时间
											zjgzts++;
										}
								}
							    int answer = shif.getSxbcs();//1=2次  2=4次  3=6次
								//当天打卡是否是最后一次   --- 归档
								List<KqglAssoDkjl> zdkcs = kqglassodkjlmapper.selectList(new QueryWrapper<KqglAssoDkjl>().lambda().eq(KqglAssoDkjl::getUserId, user.getEmpnum())
										 .ne(KqglAssoDkjl::getStatus, 0).gt(KqglAssoDkjl::getDktime, startDatestop).lt(KqglAssoDkjl::getDktime, endDatestop));
								
								KqglAssoDkmx dkmc1 = KqglAssoDkmx.builder().build().selectOne(new QueryWrapper<KqglAssoDkmx>().lambda().eq(KqglAssoDkmx::getUserid, user.getEmpnum())
										.gt(KqglAssoDkmx::getDksj, startDatestop).lt(KqglAssoDkmx::getDksj, endDatestop));
									if(isyessum == null) {//无汇总记录
										 KqglAssoMonthPunchSummary summary = KqglAssoMonthPunchSummary.builder().name(user.getEmpname()).num(user.getEmpnum()).dept(user.getDepartment())
												 .post(user.getPosition()).attGroup(attgro.getId()).build();
										 summary.setDaysOnDuty(daysOnDuty);//应出勤天数
										 summary.setActualAttDays(Double.valueOf(dkjl));//实际出勤天数
										 summary.setDaysOff(daysOff);//休息天数
										 summary.setWorkingHours(dkmc1.getGzsc());
										 int lateTimes = 0,leavetimes = 0,sbqkcs = 0,xbqkcs = 0;double lateHours = 0,earlyleave=0;
										 if(answer == 1 || answer == 2 || answer == 3) {
											 if(dkmc1.getSbdk1jg() > 0) {lateTimes++;}
											 if(dkmc1.getXbdk1jg() > 0) {leavetimes++;}
											 lateHours =  dkmc1.getSbdk1jg();
											 earlyleave = dkmc1.getXbdk1jg();
											 if(dkmc1.getSbdk1() == null) {sbqkcs++;}
											 if(dkmc1.getXbdk1() == null) {xbqkcs++;}
										 }
										 if(answer == 2 || answer == 3) {
											 if(dkmc1.getSbdk2jg() > 0) {lateTimes++;}
											 if(dkmc1.getXbdk2jg() > 0) {leavetimes++;}
											 lateHours = lateHours + dkmc1.getSbdk2jg();
											 earlyleave = earlyleave + dkmc1.getXbdk2jg();
											 if(dkmc1.getSbdk2() == null) {sbqkcs++;}
											 if(dkmc1.getXbdk2() == null) {xbqkcs++;}
										 }
										 if(answer == 3) {
											 if(dkmc1.getSbdk3jg() > 0) {lateTimes++;}
											 if(dkmc1.getXbdk3jg() > 0) {leavetimes++;}
											 lateHours = lateHours + dkmc1.getSbdk3jg();
											 earlyleave = earlyleave + dkmc1.getXbdk3jg();
											 if(dkmc1.getSbdk3() == null) {sbqkcs++;}
											 if(dkmc1.getXbdk3() == null) {xbqkcs++;}
										 }
										 summary.setLateTimes(Double.valueOf(lateTimes));//迟到次数
										 summary.setLateHours(lateHours);//迟到时长(分钟)
										 summary.setSeriousLateTimes(Double.valueOf(dkmc1.getYzcdcs()));
										 summary.setSeriousLateHours(dkmc1.getYzcdsc());
										 summary.setAbsenLateTimes(Double.valueOf(dkmc1.getKgcdfzs()));
										 summary.setEarlyLeaveTimes(Double.valueOf(leavetimes));//早退次数
										 summary.setLengthEarlyLeave(earlyleave);//早退时长(分钟)
										 summary.setNumberWorkCardShortage(Double.valueOf(sbqkcs));
										 summary.setNumberDutyCardShortage(Double.valueOf(xbqkcs));
										 int absenteeismdays=0;
										 if(zjgzts-dkjl > 0) { absenteeismdays = zjgzts-dkjl; }
										 summary.setAbsenteeismDays(Double.valueOf(absenteeismdays));//旷工天数
										 
										 //出差时长
										 //外出时长
										 //加班总时长
										 //工作日(转调休)
										 //休息日(转调休)
										 //节假日(转调休)
										 //工作日(转加班费)
										 //休息日(转加班费)
										 //节假日(转加班费)
										 
										 summary.setBelongYear(ca.get(Calendar.YEAR));
										 summary.setBelongMonth(ca.get(Calendar.MONTH)+1);
										 summary.setOrgCode(org_code);
										 summary.setLastModified(new Date().getTime());
										 /******审批接口----对接*******/
										 
									 }else {
										 int id = isyessum.getId();
										 
									 }
							    
							    
							}else {
								System.out.println("该员工未加入考勤组");
							}
						
					}
				}
			}
			/****************************************************************/
			KqglTaskTiming.builder().task("AttendanceTask").id(sock.getId()).executionStatus(0).lastExecutionTime(new Date().getTime()).build().updateById();
			return new Exception().getStackTrace()[0].getMethodName();
			
		}else {
			return null;
		}
	}
	
  
}