package org.fouram.service;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.fouram.core.base.service.BaseService;
import org.fouram.core.plugin.weixin.cp.util.WXCpOaUtil;
import org.fouram.core.util.BeanUtils;
import org.fouram.core.util.DateUtil;
import org.fouram.core.util.Tools;
import org.fouram.entity.SapCheck;
import org.fouram.entity.SapCheckReport;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

import me.chanjar.weixin.cp.bean.oa.WxCpCheckinData;

@Service
public class SapCheckService extends BaseService {

	@Autowired
	private WxUserService wxUserService;

	public void saveCheckInOffOuts(String startDay, String endDay) throws Exception {
		// 重新生成制定日期范围内的打卡数据
		update("SapCheckMapper.deleteCheckinList", null);
		update("SapCheckMapper.deleteCheckoffList", null);
		update("SapCheckMapper.deleteCheckoutList", null);

		Date startDate = DateUtil.sdfTime.parse(startDay + " 00:00:00");
		Date endDate = DateUtil.sdfTime.parse(endDay + " 23:59:59");

		List<String> userIds = wxUserService.selectAllUserIds();
		Map<String, List<String>> map = groupList(userIds);
		for (String key : map.keySet()) {
			List<WxCpCheckinData> checkinDatas = WXCpOaUtil.getCheckinData(startDate, endDate, map.get(key));
			for (WxCpCheckinData data : checkinDatas) {
				SapCheck check = new SapCheck();
				BeanUtils.copyProperties(data, check);
				check.setCheckinDate(new Date(check.getCheckinTime() * 1000));
				check.setCheckinDay(DateUtil.getDay(check.getCheckinDate()));
				if (data.getCheckinType().equals("上班打卡")) {
					saveCheckin(check);
				} else if (data.getCheckinType().equals("下班打卡")) {
					saveCheckoff(check);
				} else if (data.getCheckinType().equals("外出打卡")) {
					saveCheckout(check);
				} else {
					System.out.println(data);
				}
			}
		}

		// 生成制定日期每天外出打开开始和结束时间
		update("SapCheckMapper.deleteCheckoutStartList", null);
		update("SapCheckMapper.deleteCheckoutEndList", null);
		update("SapCheckMapper.saveCheckoutStart1", null);
		update("SapCheckMapper.saveCheckoutStart2", null);
		update("SapCheckMapper.saveCheckoutEnd", null);
		
		// 删除重复数据
		updateRepeatCheckDelete();
	}

	public Long queryCheckInTotal() throws Exception {
		return (Long) findObject("SapCheckMapper.queryCheckInTotal", null);
	}

	public void saveCheckin(SapCheck check) throws Exception {
		save("SapCheckMapper.saveCheckin", check);
	}

	public void saveCheckoff(SapCheck check) throws Exception {
		save("SapCheckMapper.saveCheckoff", check);
	}

	public void saveCheckout(SapCheck check) throws Exception {
		save("SapCheckMapper.saveCheckout", check);
	}

	@SuppressWarnings("unchecked")
	public void updateRepeatCheckDelete() throws Exception {
		// 处理重复数据
		List<SapCheck> sapChecks = (List<SapCheck>) findList("SapCheckMapper.selectRepeatCheckin", null);
		Set<String> checkinDays = Sets.newHashSet();
		for (SapCheck sapCheck : sapChecks) {
			if (!checkinDays.contains(sapCheck.getCheckinDay() + sapCheck.getUserId())) {
				checkinDays.add(sapCheck.getCheckinDay() + sapCheck.getUserId());
			} else {
				update("SapCheckMapper.deleteCheckinById", sapCheck);
			}
		}

		sapChecks = (List<SapCheck>) findList("SapCheckMapper.selectRepeatCheckoff", null);
		checkinDays = Sets.newHashSet();
		for (SapCheck sapCheck : sapChecks) {
			if (!checkinDays.contains(sapCheck.getCheckinDay() + sapCheck.getUserId())) {
				checkinDays.add(sapCheck.getCheckinDay() + sapCheck.getUserId());
			} else {
				update("SapCheckMapper.deleteCheckoffById", sapCheck);
			}
		}

		sapChecks = (List<SapCheck>) findList("SapCheckMapper.selectRepeatCheckoutStart", null);
		checkinDays = Sets.newHashSet();
		for (SapCheck sapCheck : sapChecks) {
			if (!checkinDays.contains(sapCheck.getCheckinDay() + sapCheck.getUserId())) {
				checkinDays.add(sapCheck.getCheckinDay() + sapCheck.getUserId());
			} else {
				update("SapCheckMapper.deleteCheckoutStartById", sapCheck);
			}
		}

		sapChecks = (List<SapCheck>) findList("SapCheckMapper.selectRepeatCheckoutEnd", null);
		checkinDays = Sets.newHashSet();
		for (SapCheck sapCheck : sapChecks) {
			if (!checkinDays.contains(sapCheck.getCheckinDay() + sapCheck.getUserId())) {
				checkinDays.add(sapCheck.getCheckinDay() + sapCheck.getUserId());
			} else {
				update("SapCheckMapper.deleteCheckoutEndById", sapCheck);
			}
		}
	}

	@SuppressWarnings("unchecked")
	public void saveReportResultData(String startDay, String endDay) throws Exception {
		Map<String, String> param = Maps.newHashMap();
		param.put("startDay", startDay);
		param.put("endDay", endDay);
		param.put("startDayT", startDay.replace("-", ""));
		param.put("endDayT", endDay.replace("-", ""));

		// 生成报表数据
		update("SapCheckMapper.deleteCheckReport", param);
		update("SapCheckMapper.saveCheckReport", param);
		// 更新华人时代人员上班时间可以推迟30分钟
		update("SapCheckMapper.updateHrsdWorkTime", param);
		// 更新所有异常事件的数据为异常数据
		update("SapCheckMapper.updateAllExceptionResult", param);
		// 查询有请假情况的数据
		List<SapCheckReport> checkReports = (List<SapCheckReport>) findList("SapCheckMapper.selectLeaveDayList", param);
		for (SapCheckReport checkReport : checkReports) {
			if (Tools.isInteger(checkReport.getLeaveDay())) {
				update("SapCheckMapper.updateResultOk", checkReport.getId());
			} else {
				// 0.5
				if (isOkWorkTime(checkReport) || isOkOffWorkTime(checkReport)
						|| StringUtils.isNotBlank(checkReport.getBukaDay())) {
					update("SapCheckMapper.updateResultOk", checkReport.getId());
				}
			}
		}
		// 获取异常数据，更新部分符合条件的正常
		checkReports = (List<SapCheckReport>) findList("SapCheckMapper.selectExceptionList", param);
		for (SapCheckReport checkReport : checkReports) {
			if (isOkWorkTime(checkReport) || isOkOffWorkTime(checkReport)
					|| StringUtils.isNotBlank(checkReport.getBukaDay())) {
				update("SapCheckMapper.updateResultOk", checkReport.getId());
			}
		}
	}

	// 是不是正确的上班时间
	private boolean isOkWorkTime(SapCheckReport checkReport) throws Exception {
		if (StringUtils.isBlank(checkReport.getCheckinException())) {
			return true;
		}
		if (StringUtils.isNotBlank(checkReport.getCheckoutDate1())) {
			if (DateUtil.sdfTime.parse(checkReport.getCheckoutDate1()).getTime() <= DateUtil.sdfsTime
					.parse(checkReport.getCheckinDay() + " " + checkReport.getWorkTime()).getTime()) {
				return true;
			}
		}
		if (StringUtils.isNotBlank(checkReport.getCheckoutDate2())) {
			if (DateUtil.sdfTime.parse(checkReport.getCheckoutDate2()).getTime() <= DateUtil.sdfsTime
					.parse(checkReport.getCheckinDay() + " " + checkReport.getWorkTime()).getTime()) {
				return true;
			}
		}
		return false;
	}

	// 是不是正确的下班时间
	private boolean isOkOffWorkTime(SapCheckReport checkReport) throws Exception {
		if (StringUtils.isBlank(checkReport.getCheckoffException())) {
			return true;
		}
		if (StringUtils.isNotBlank(checkReport.getCheckoutDate1())) {
			if (DateUtil.sdfTime.parse(checkReport.getCheckoutDate1()).getTime() >= DateUtil.sdfsTime
					.parse(checkReport.getCheckinDay() + " " + checkReport.getWorkTime()).getTime()) {
				return true;
			}
		}
		if (StringUtils.isNotBlank(checkReport.getCheckoutDate2())) {
			if (DateUtil.sdfTime.parse(checkReport.getCheckoutDate2()).getTime() >= DateUtil.sdfsTime
					.parse(checkReport.getCheckinDay() + " " + checkReport.getOffWorkTime()).getTime()) {
				return true;
			}
		}
		return false;
	}

	public JSONObject findUserReportPage(String startDate, String endDate, String departId, String name, String state,
			Integer pageSize, Integer pageNumber) throws Exception {
		List<Map<String, String>> list = findUserReports(startDate, endDate, departId, name, state, pageSize,
				pageNumber);
		Long total = findUserReportTotal(startDate, endDate, departId, name, state);
		return getPageResult(list, total);
	}

	@SuppressWarnings("unchecked")
	public List<Map<String, String>> findUserReports(String startDate, String endDate, String departId, String name,
			String state, Integer pageSize, Integer pageNumber) throws Exception {
		if (StringUtils.isNotBlank(departId) && departId.endsWith(",")) {
			departId = departId.substring(0, departId.length() - 1);
		}
		if (StringUtils.isNotBlank(state)) {
			if ("1".equals(state)) {
				state = "正常";
			} else {
				state = "异常";
			}
		}
		Map<String, String> pd = Maps.newHashMap();
		pd.put("startDate", startDate);
		pd.put("endDate", endDate);
		pd.put("departId", departId);
		pd.put("name", name);
		pd.put("state", state);
		if (pageSize != null) {
			pd.put("pageCurrent", String.valueOf(pageSize * (pageNumber - 1)));
			pd.put("pageSize", String.valueOf(pageSize));
		}
		return (List<Map<String, String>>) findList("SapCheckMapper.findUserReports", pd);
	}
	
	public Long findUserReportTotal(String startDate, String endDate, String departId, String name,
			String state) throws Exception {
		if (StringUtils.isNotBlank(departId) && departId.endsWith(",")) {
			departId = departId.substring(0, departId.length() - 1);
		}
		if (StringUtils.isNotBlank(state)) {
			if ("1".equals(state)) {
				state = "正常";
			} else {
				state = "异常";
			}
		}
		Map<String, String> pd = Maps.newHashMap();
		pd.put("startDate", startDate);
		pd.put("endDate", endDate);
		pd.put("departId", departId);
		pd.put("name", name);
		pd.put("state", state);
		return (Long) findObject("SapCheckMapper.findUserReportTotal", pd);
	}
	
	public static JSONObject getPageResult(List<? extends Object> list, Object total){
		JSONObject object = new JSONObject();
		object.put("total", total);
		object.put("data", list);
		return object;
	}
}