package com.kingdee.shr.customer.gtiit.handler;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.kingdee.eas.hr.ats.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.ui.ModelMap;
import org.springframework.util.LinkedMultiValueMap;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.eas.framework.CoreBaseInfo;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.ats.web.handler.AtsOverTimeBillBatchEditHandler;
import com.kingdee.shr.base.syssetting.context.SHRContext;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
import com.kingdee.shr.base.syssetting.web.json.JSONUtils;
import com.kingdee.shr.customer.gtiit.util.BaseUtil;
import com.kingdee.shr.customer.gtiit.util.DateTimeUtils;

/**
 * 多人加班单表单Handler
 * @author xiaoxin
 *
 */
public class AtsOverTimeBillBatchEditHandlerEx extends AtsOverTimeBillBatchEditHandler{





	private static Logger logger = Logger.getLogger("com.kingdee.shr.customer.gtiit.handler.AtsOverTimeBillBatchEditHandlerEx");

	public void workMultipleAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
		Context ctx = SHRContext.getInstance().getContext();
		String otDate = request.getParameter("otDate");
		logger.error("加班日期："+otDate);
		String sql = "SELECT b.CFWORKMULTIPLE FROM T_HR_ATS_LegalHoliday a left join T_HR_ATS_LegalHolidayItem b on a.fid = b.FGROUPID where a.FSTATE = '1' and b.FSTARTDATE <= '"+otDate+"' and b.FENDDATE >= '"+otDate+"'";
		logger.error("查询加班类型SQL："+sql);
		Map<String, Map<String, String>> overTimeTypeMap = BaseUtil.getOverTimeType(ctx);
		Map<String, String> returnMap = new HashMap<String, String>();
		try {
			IRowSet iRowSet = DbUtil.executeQuery(ctx, sql);
			while (iRowSet.next()){
				if(iRowSet.getString("CFWORKMULTIPLE").equals("1")){
					//工作日加班
					returnMap = overTimeTypeMap.get("001");
				}else if(iRowSet.getString("CFWORKMULTIPLE").equals("2")){
					//休息日加班
					returnMap = overTimeTypeMap.get("002");
				}else if(iRowSet.getString("CFWORKMULTIPLE").equals("3")){
					//法定节假日加班
					returnMap = overTimeTypeMap.get("003");
				}
			}
		} catch (BOSException e) {
			e.printStackTrace();
		} catch (SQLException throwables) {
			throwables.printStackTrace();
		}
		JSONUtils.writeJson(response, returnMap);
	}
	
	public void jobTypeAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
		Calendar calendar = Calendar.getInstance();
		Context ctx = SHRContext.getInstance().getContext();
		Map<String, Map<String, String>> overTimeTypeMap = BaseUtil.getOverTimeType(ctx);
		Map<String, String> returnMap = new HashMap<String, String>();
		String otDate = request.getParameter("otDate");
		logger.error("加班日期:"+otDate);
		Date parseDate = DateTimeUtils.parseDate(otDate, "yyyy-MM-dd");
		calendar.setTime(parseDate);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        if(dayOfWeek == Calendar.SATURDAY || dayOfWeek == Calendar.SUNDAY) {
			//休息日加班
        	returnMap = overTimeTypeMap.get("002");
        }else {
			//工作日加班
        	returnMap = overTimeTypeMap.get("001");
        }
        JSONUtils.writeJson(response, returnMap);
	}
	
	@Override
	protected void verifyModel(HttpServletRequest request, HttpServletResponse response, CoreBaseInfo model)
			throws SHRWebException {
		super.verifyModel(request, response, model);
		checkOverTime(model);
		checkCompensate(model);
	}
	
	@Override
	protected void beforeSubmit(HttpServletRequest request, HttpServletResponse response, CoreBaseInfo model)
			throws SHRWebException
	{

		super.beforeSubmit(request, response, model);
		checkOverTime(model);
		checkCompensate(model);
		countSumTime(model);
	}

	public void submitEffectAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap)
			throws SHRWebException, BOSException
	{
		CoreBaseInfo model = (CoreBaseInfo)request.getAttribute("dynamic_model");
		countSumTime(model);
		super.submitEffectAction(request, response, modelMap);
	}




	private void countSumTime(CoreBaseInfo model)
			throws ShrWebBizException
	{
		logger.error("进入多人加班单提交重算时间方法");
		AtsOverTimeBillInfo billInfo = (AtsOverTimeBillInfo)model;
		AtsOverTimeBillEntryCollection entries = billInfo.getEntries();
		BigDecimal weekdayHour = BigDecimal.ZERO;
		BigDecimal restdayHour = BigDecimal.ZERO;
		BigDecimal holidayHour = BigDecimal.ZERO;
		BigDecimal totalDuration = BigDecimal.ZERO;
		BigDecimal compensatoryTotal = BigDecimal.ZERO;
		BigDecimal totalOvertimePay = BigDecimal.ZERO;
		for (int i = 0; i < entries.size(); i++) {
			AtsOverTimeBillEntryInfo entryInfo = entries.get(i);
			String otTypeId = "";
			String otCompensId = "";

			OverTimeTypeInfo otType = entryInfo.getOtType();

			BigDecimal applyOtTime = entryInfo.getApplyOTTime() == null ? BigDecimal.ZERO : entryInfo.getApplyOTTime();

			OverTimeCompensInfo otCompens = entryInfo.getOtCompens();
			if (otType != null) {
				otTypeId = otType.getId().toString();
			}
			if (otCompens != null) {
				otCompensId = otCompens.getId().toString();
			}
			if (StringUtils.equals(otTypeId, "rBy0u1YgQ9C1OxcM85mxyY6C/nU="))
				weekdayHour = weekdayHour.add(applyOtTime);
			else if (StringUtils.equals(otTypeId, "zr+ur5D4RA+2bdVZ2VPqp46C/nU="))
				restdayHour = restdayHour.add(applyOtTime);
			else if (StringUtils.equals(otTypeId, "sRWUOt7sRpOY0TCo6NMqGY6C/nU=")) {
				holidayHour = holidayHour.add(applyOtTime);
			}

			if (StringUtils.equals(otCompensId, "AERg0TIcSnaM40EKvJCdRKlrTmA="))
				compensatoryTotal = compensatoryTotal.add(applyOtTime);
			else if (StringUtils.equals(otCompensId, "zkbt5bMLQ3ehUivmKbtBOqlrTmA=")) {
				totalOvertimePay = totalOvertimePay.add(applyOtTime);
			}
		}
		totalDuration = weekdayHour.add(restdayHour).add(holidayHour);

		billInfo.put("weekdayHour", weekdayHour);
		billInfo.put("restdayHour", restdayHour);
		billInfo.put("holidayHour", holidayHour);
		billInfo.put("totalDuration", totalDuration);
		billInfo.put("compensatoryTotal", compensatoryTotal);
		billInfo.put("totalOvertimePay", totalOvertimePay);
	}

	private void checkCompensate(CoreBaseInfo model) throws ShrWebBizException {
		Context ctx = SHRContext.getInstance().getContext();
		AtsOverTimeBillInfo billInfo = (AtsOverTimeBillInfo) model;
		AtsOverTimeBillEntryCollection entries = billInfo.getEntries();
		
		Set<String> personIdSet = new HashSet<String>();
		String compenSql = "select fid from T_HR_ATS_OverTimeCompens where fnumber='002'";
		String compenId = "";
		try {
			IRowSet compenRowSet = DbUtil.executeQuery(ctx, compenSql);
			if(compenRowSet.next()) {
				compenId = compenRowSet.getString("fid");
			}
		} catch (SQLException e1) {
			e1.printStackTrace();
		} catch (BOSException e) {
			e.printStackTrace();
		}
		for(int i=0; i<entries.size(); i++) {
			AtsOverTimeBillEntryInfo entryInfo = entries.get(i);
			if(StringUtils.equals(entryInfo.getOtCompens().getId().toString(), compenId)) {
				personIdSet.add(entryInfo.getPerson().getId().toString());
			}
		}
		logger.error("员工ID集合："+personIdSet.toString());
		StringBuffer strBuffer = new StringBuffer();
		for(String personId:personIdSet) {
			strBuffer.append("'"+personId+"',");
		}
		
		if(strBuffer.length()>0) {
			strBuffer = strBuffer.deleteCharAt(strBuffer.length()-1);
			Map<String, String> personIdByNameMap = BaseUtil.getPersonIdByName(ctx, personIdSet);
			String sql = "SELECT p.fid,emp.jobgradename FROM t_bd_person p "
					+ "left join (select gra.fname_l2 jobgradename,e.fpersonid from "
					+ "(SELECT FPERSONID,max(fleffdt) as maxDate FROM T_HR_EmpPostExperienceHis group by  FPERSONID) as h "
					+ "left join T_HR_EmpPostExperienceHis e on e.fpersonid= h.FPERSONID and fleffdt = h.maxDate "
					+ "left join (SELECT * FROM T_HR_EmpPostRank where fislatest='1') r on r.fpersonid = e.fpersonid "
					+ "left join T_HR_JobGrade gra on gra.fid=r.fjobgradeid) emp on p.fid=emp.fpersonid "
					+ "where p.fid in ("+strBuffer.toString()+")";
			try {
				IRowSet rowSet = DbUtil.executeQuery(ctx, sql);
				while(rowSet.next()) {
					String jobGradeName = rowSet.getString("jobgradename");
					if(StringUtils.isNotBlank(jobGradeName)) {
						jobGradeName = jobGradeName.replace("L", "");
						jobGradeName = jobGradeName.replace("-", ".");
						Double gradeLevel = Double.parseDouble(jobGradeName);
						if (gradeLevel >= 13D) {
							throw new ShrWebBizException("Employee ("+personIdByNameMap.get(rowSet.getString("fid"))+") with a rank greater than or equal to L13 is not allowed to submit overtime compensation forms with overtime pay as the compensation type");
						}
					}
				}
				
				String personTypeSql = "SELECT a.fid,e.fnumber  FROM T_BD_Person a "
						+ "left join (select b.fpersonid,c.CFWorkercategoryID  from (SELECT FPERSONID,max(FEFFDT) as maxDate FROM T_HR_EmpOrgRelation where fassignType = '1' group by FPERSONID) b "
						+ "left join T_HR_EmpOrgRelation c on b.fpersonid = c.fpersonid and b.maxdate=c.FEFFDT and c.fleffdt='2199-12-31' and c.fassignType = '1') d on a.fid=d.fpersonid "
						+ "left join CT_MP_WorkerCategory e on e.fid=d.CFWorkercategoryID "
						+ "where a.fid in ("+strBuffer.toString()+") o ";
				IRowSet personTypeRow = DbUtil.executeQuery(ctx, personTypeSql);
				while(personTypeRow.next()) {
					String workCategoryNumber = personTypeRow.getString("fnumber");
					if(StringUtils.equals("GTIIT_FACULTY", workCategoryNumber) || StringUtils.equals("GTIIT_OTHER", workCategoryNumber)) {
						throw new ShrWebBizException("Employee ("+personIdByNameMap.get(personTypeRow.getString("fid"))+") is an academic staff member and cannot submit overtime compensation forms with overtime pay as the compensation method");
					}
				}
			} catch (BOSException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
		}
		
	}
	private void checkOverTime(CoreBaseInfo model) throws ShrWebBizException {
		Context ctx = SHRContext.getInstance().getContext();
		AtsOverTimeBillInfo billInfo = (AtsOverTimeBillInfo) model;
		AtsOverTimeBillEntryCollection entries = billInfo.getEntries();
		LinkedMultiValueMap<String, Map<String, Date>> multiMap = new LinkedMultiValueMap<>();
		StringBuffer personIdBuffer = new StringBuffer();
		for(int i=0; i<entries.size(); i++) {
			AtsOverTimeBillEntryInfo entryInfo = entries.get(i);
			if(!entryInfo.getOtType().getString("id").equals("rBy0u1YgQ9C1OxcM85mxyY6C/nU=")) {
				continue;
			}
			Date otDate = entryInfo.getOtDate();
			String dateFormat = DateTimeUtils.dateFormat(otDate, "yyyy-MM-dd");
			String sql = "SELECT b.CFWORKMULTIPLE FROM T_HR_ATS_LegalHoliday a left join T_HR_ATS_LegalHolidayItem b on a.fid = b.FGROUPID where a.FSTATE = '1' and b.FSTARTDATE <= '"+dateFormat+"' and b.FENDDATE >= '"+dateFormat+"'";
			try {
				IRowSet iRowSet = DbUtil.executeQuery(ctx, sql);
				if(iRowSet.next()) {
					continue;
				}
			} catch (BOSException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			
			Map<String, Date> map = new HashMap<>();
			map.put("startTime", entryInfo.getStartTime());
			map.put("endTime", entryInfo.getEndTime());
			multiMap.add(entryInfo.getPerson().getString("id"), map);
			personIdBuffer.append("'"+entryInfo.getPerson().getString("id")+"',");
		}
		Map<String, String> personIdByNameMap = BaseUtil.getPersonIdByName(ctx, multiMap.keySet());
		if(personIdBuffer.length()>0) {
			String sql = "SELECT a.FPROPOSERID,c.FRESTPRETIME,c.FRESTNEXTTIME FROM T_HR_ATS_AttendanceFile a left join T_HR_ATS_Shift b on a.FATSSHIFTID = b.fid left join T_HR_ATS_ShiftItem c on c.FGROUPID = b.fid "
					+ "where FPROPOSERID in ("+personIdBuffer.deleteCharAt(personIdBuffer.length()-1)+") and  a.FATTENDFILESTATE = '"+AttendFileStateEnum.ENABLE_VALUE+"'";
			try {
				IRowSet rowSet = DbUtil.executeQuery(ctx, sql);
				while(rowSet.next()) {
					String personId = rowSet.getString("FPROPOSERID");
					String restStart = rowSet.getObject("FRESTPRETIME")==null?"12:00":rowSet.getString("FRESTPRETIME");
					String restEnd = rowSet.getObject("FRESTNEXTTIME")==null?"13:30":rowSet.getString("FRESTNEXTTIME");
					List<Map<String, Date>> list = multiMap.get(personId);
					for(Map<String, Date> dateMap:list) {
						Date startTime = dateMap.get("startTime");
						Date endTime = dateMap.get("endTime");
						Instant startInstant = startTime.toInstant();
						Instant endInstant = endTime.toInstant();
						LocalTime startLocalTime = startInstant.atZone(ZoneId.systemDefault()).toLocalTime();
						LocalTime endLocalTime = endInstant.atZone(ZoneId.systemDefault()).toLocalTime();
						
						LocalTime shiftStartTime = LocalTime.parse(restStart);
						LocalTime shiftendTime = LocalTime.parse(restEnd);
						if(startLocalTime.compareTo(shiftendTime)>=0 || endLocalTime.compareTo(shiftStartTime)<=0) {
							continue;
						}
						if((startLocalTime.compareTo(shiftStartTime)>=0 && startLocalTime.compareTo(shiftendTime)<=0) 
								|| (endLocalTime.compareTo(shiftStartTime)>=0 && endLocalTime.compareTo(shiftendTime)<=0)) {
							throw new ShrWebBizException("Employee ("+personIdByNameMap.get(personId)+") cannot work overtime during rest time on weekdays");
						}
					}
				}
			} catch (BOSException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}


}
