package com.kingdee.eas.custom.facade;

import java.math.BigDecimal;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.utils.DateTimeUtils;
import com.kingdee.eas.custom.utils.SplitLeaveUtils;
import com.kingdee.eas.framework.CoreBaseCollection;
import com.kingdee.eas.hr.ats.AtsLeaveBillCollection;
import com.kingdee.eas.hr.ats.AtsLeaveBillEntryCollection;
import com.kingdee.eas.hr.ats.AtsLeaveBillEntryFactory;
import com.kingdee.eas.hr.ats.AtsLeaveBillEntryInfo;
import com.kingdee.eas.hr.ats.AtsLeaveBillFactory;
import com.kingdee.eas.hr.ats.AtsLeaveBillInfo;
import com.kingdee.eas.hr.ats.HolidayPolicyCollection;
import com.kingdee.eas.hr.ats.HolidayPolicyFactory;
import com.kingdee.eas.hr.ats.HolidayTypeCollection;
import com.kingdee.eas.hr.ats.HolidayTypeFactory;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;

public class SickQuotaFacadeControllerBean extends AbstractSickQuotaFacadeControllerBean
{
    private static Logger logger =
        Logger.getLogger("com.kingdee.eas.custom.facade.SickQuotaFacadeControllerBean");
    
    @Override
    protected void _createQuota(Context ctx, String executeDate) throws BOSException, EASBizException {
    	try {
    		Date nowDate = new Date();
    		logger.error("日期参数："+executeDate);
    		if(StringUtils.isNotBlank(executeDate)) {
    			nowDate = DateTimeUtils.parseDate(executeDate, "yyyy-MM-dd");
    		} 
    		
    		Calendar calendar = Calendar.getInstance();
    		calendar.setTime(nowDate);
    		
    		String dateFormat = DateTimeUtils.dateFormat(nowDate, "yyyy-MM-dd");
    		BigDecimal zero = BigDecimal.ZERO;
    		
    		String holidayPolicyIds = this.getHolidayPolicyIds(ctx, "JQLX000003Y");
    	    logger.error("假期制度为病假的id集合："+holidayPolicyIds);
    	    if(StringUtils.isBlank(holidayPolicyIds)) {
    	    	return;
    	    }
    	    //获取该月已授予的额度
    	    String realitySql = "select cfpersonid,CFRealityGrantLimit from CT_CUS_SickLeaveLimit where year(cfmonth) = "+calendar.get(Calendar.YEAR)+" and month(cfmonth) = "+(calendar.get(Calendar.MONTH)+1)+" and (cfisimport is null or cfisimport <> '1') and CFIsGrant = '1'";
    	    logger.error("获取该月已授予额度sql:"+realitySql);
    	    IRowSet realityRow = DbUtil.executeQuery(ctx, realitySql);
    	    Map<String, BigDecimal> realityMap = new HashMap<>();
    	    while(realityRow.next()) {
    	    	realityMap.put(realityRow.getString("cfpersonid"), realityRow.getBigDecimal("CFRealityGrantLimit"));
    	    }
    	    
    	    String countSql = "select count(1) count from CT_CUS_SickLeaveLimit where (cfisimport is null or cfisimport <> '1')";
    	    logger.error("是否已初始化SQL额度："+countSql);
    	    IRowSet countRow = DbUtil.executeQuery(ctx, countSql);
    	    BigDecimal dataCount = zero;
    	    while(countRow.next()) {
    	    	dataCount = countRow.getBigDecimal("count")==null?zero:countRow.getBigDecimal("count");
    	    }
    	    
    	    //删除当月非导入的数据
    		String deleteSql = "delete from CT_CUS_SickLeaveLimit where year(cfmonth) = "+calendar.get(Calendar.YEAR)+" and month(cfmonth) = "+(calendar.get(Calendar.MONTH)+1)+" and (cfisimport is null or cfisimport <> '1')";
    		logger.error("删除当月非导入数据sql:"+deleteSql);
    		DbUtil.execute(ctx, deleteSql);
    		
			String sql = "select e.fpersonid personid,p.cffse fse,p.cffsme fsme,w.fname_l2 percategoryname,w.fnumber percategoryNumber,r.fenterdate enterdate from T_HR_EmpOrgRelation e " +
					"left join T_BD_Person p on e.fpersonid=p.fid " +
					"left join CT_MP_WorkerCategory w on e.cfworkercategoryid=w.fid " +
					"left join T_HR_EmpLaborRelationHis r on r.FPERSONID=e.fpersonid " +
					"left join T_HR_BDEmployeeType b on b.fid=r.flaborrelationstateid " +
					"where e.feffdt <= '"+dateFormat+"' and e.fleffdt >= '"+dateFormat+"' and e.fassignType = '1' and e.fislatestinaday = '1' " +
					"and b.finservice not in ('2','3') and r.fstartdatetime <= '"+dateFormat+"' and r.fenddatetime >= '"+dateFormat+"' " +
					"and e.fpersonid in (select FPROPOSERID from T_HR_ATS_HolidayLimit where FHOLIDAYPOLICYID in ("+holidayPolicyIds+") )";
			logger.error("查询员工病假信息SQL："+sql);
			StringBuffer strBuffer = new StringBuffer();
			StringBuffer uptBuffer = new StringBuffer();
			
			String holidaySql = "select b.fid,b.fremainlimit,b.fstandardlimit,b.fproposerid from (SELECT fproposerid,max(FEFFECTDATE) maxdate FROM T_HR_ATS_HolidayLimit where FHOLIDAYPOLICYID in ("+holidayPolicyIds+") group by fproposerid) a left join T_HR_ATS_HolidayLimit b on a.fproposerid = b.fproposerid and a.maxdate = b.FEFFECTDATE where b.FHOLIDAYPOLICYID in ("+holidayPolicyIds+")";
			logger.error("查询员工假期额度信息SQL："+holidaySql);
			IRowSet holidayRow = DbUtil.executeQuery(ctx, holidaySql);
			Map<String, BigDecimal> holidayMap = new HashMap<>();
			Map<String, String> personHolidayMap = new HashMap<>();
			Map<String, BigDecimal> standLimitMap = new HashMap<>();
			while (holidayRow.next()){
				personHolidayMap.put(holidayRow.getString("fproposerid"), holidayRow.getString("fid"));
				holidayMap.put(holidayRow.getString("fproposerid"), holidayRow.getObject("fremainlimit")==null?zero:holidayRow.getBigDecimal("fremainlimit"));
				standLimitMap.put(holidayRow.getString("fproposerid"), holidayRow.getObject("fstandardlimit")==null?zero:holidayRow.getBigDecimal("fstandardlimit"));
			}
			
			//初始额度
			String initialSql = "SELECT cfpersonid,cfinitiallimit FROM CT_CUS_SickLeaveLimit where cfisimport = '1' and cfpersonid not in (SELECT FPROPOSERID FROM T_HR_ATS_HolidayLimit where FHOLIDAYPOLICYID in ("+holidayPolicyIds+") group by FPROPOSERID having count(1)>1)";
			logger.error("查询员工初始额度信息SQL："+initialSql);
			IRowSet initialRow = DbUtil.executeQuery(ctx, initialSql);
			Map<String, BigDecimal> initialMap = new HashMap<>();
			while (initialRow.next()){
				initialMap.put(initialRow.getString("cfpersonid"), initialRow.getObject("cfinitiallimit")==null?zero:initialRow.getBigDecimal("cfinitiallimit"));
			}
			
			//员工历史每月实际授予额度汇总
			String grantSql = "SELECT cfpersonid,sum(CFRealityGrantLimit) sumGrantLimit FROM CT_CUS_SickLeaveLimit where (cfisimport is null or cfisimport <> '1') and cfholidayid in (select b.fid from (SELECT fproposerid,max(FEFFECTDATE) maxdate FROM T_HR_ATS_HolidayLimit where FHOLIDAYPOLICYID in ("+holidayPolicyIds+") group by fproposerid) a left join T_HR_ATS_HolidayLimit b on a.fproposerid = b.fproposerid and a.maxdate = b.FEFFECTDATE where b.FHOLIDAYPOLICYID in ("+holidayPolicyIds+")) group by cfpersonid";
			IRowSet grantRow = DbUtil.executeQuery(ctx, grantSql);
			Map<String, BigDecimal> grantMap = new HashMap<>();
			while (grantRow.next()){
				grantMap.put(grantRow.getString("cfpersonid"), grantRow.getObject("sumGrantLimit")==null?zero:grantRow.getBigDecimal("sumGrantLimit"));
			}
			
			calendar.set(Calendar.DAY_OF_MONTH, 1);
			calendar.add(Calendar.MONTH, 1);
			String nextDateFormat = DateTimeUtils.dateFormat(calendar.getTime(), "yyyy-MM-dd");
			String leaveSql = "SELECT a.fid billId,b.fid entryId FROM T_HR_ATS_LeaveBill a left join T_HR_ATS_LeaveBillEntry b on a.FID = b.FBILLID left join T_HR_ATS_HolidayPolicy c on b.FPOLICYID = c.FID left join T_HR_ATS_HolidayType d on c.FHOLIDAYTYPEID = d.FID "
					+ "where d.FNUMBER = 'JQLX000003Y' and a.FBILLSTATE in ('1','2','3') and b.FREALENDTIME >= '"+nextDateFormat+"' ";
//			String leaveSql = "SELECT top 2 a.fid billId,b.fid entryId FROM T_HR_ATS_LeaveBill a left join T_HR_ATS_LeaveBillEntry b on a.FID = b.FBILLID left join T_HR_ATS_HolidayPolicy c on b.FPOLICYID = c.FID left join T_HR_ATS_HolidayType d on c.FHOLIDAYTYPEID = d.FID "
//					+ "where d.FNUMBER = 'JQLX000001Y'";
			IRowSet leaveRow = DbUtil.executeQuery(ctx, leaveSql);
			StringBuffer leaveBuffer = new StringBuffer();
			while(leaveRow.next()) {
				leaveBuffer.append("'"+leaveRow.getString("billId")+"',");
			}
			
			//额度拆分
			List<Map<String, Object>> leaveDetailList = new ArrayList<>();
			if(leaveBuffer.length()>0) {
				leaveBuffer = leaveBuffer.deleteCharAt(leaveBuffer.length()-1);
				AtsLeaveBillCollection atsLeaveBillCollection = AtsLeaveBillFactory.getLocalInstance(ctx).getAtsLeaveBillCollection("where id in ("+leaveBuffer.toString()+")");
				for(int i = 0;i<atsLeaveBillCollection.size();i++) {
					AtsLeaveBillInfo atsLeaveBillInfo = atsLeaveBillCollection.get(i);
					AtsLeaveBillEntryCollection entryColl = atsLeaveBillInfo.getEntries();
					for(int j = 0;j<entryColl.size();j++) {
						AtsLeaveBillEntryInfo entryInfo = entryColl.get(j);
						Date realEndDate = new Date(entryInfo.getRealEndTime().getTime());
						//只拆分实际结束日期在本月之后的
						if(realEndDate.compareTo(calendar.getTime())<0) {
							continue;
						}
						SplitLeaveUtils splitLeaveUtils = new SplitLeaveUtils(ctx, atsLeaveBillInfo, entryInfo);
						leaveDetailList.addAll(splitLeaveUtils.getSplitLeaveBill());
					}
				}
			}
			Map<String, BigDecimal> leaveLimitMap = new HashMap<>();
			for(int i=0;i<leaveDetailList.size();i++) {
				Map<String, Object> detailMap = leaveDetailList.get(i);
				Date currDate = (Date) detailMap.get("currDate");
				String personId = (String) detailMap.get("personId");
				BigDecimal leaveLength = (BigDecimal)detailMap.get("leaveLength");
				//只统计日期在本月之后的
				if(currDate.compareTo(calendar.getTime())<0) {
					continue;
				}
				if(leaveLimitMap.containsKey(personId)) {
					BigDecimal personLeave = leaveLimitMap.get(personId);
					leaveLimitMap.put(personId, personLeave.add(leaveLength));
				}else {
					leaveLimitMap.put(personId, leaveLength);
				}
			}
			
			IRowSet iRowSet = DbUtil.executeQuery(ctx, sql);
			int count = 0;
			while (iRowSet.next()){
				String personId = iRowSet.getString("personid");
				String percategoryNumber = iRowSet.getString("percategoryNumber")==null?"":iRowSet.getString("percategoryNumber");
				BigDecimal sickQuota = iRowSet.getObject("fse")==null?zero:iRowSet.getBigDecimal("fse");
				BigDecimal highestQuota = iRowSet.getObject("fsme")==null?zero:iRowSet.getBigDecimal("fsme");
				//行政人员
				if(percategoryNumber.equals("GTIIT_GAS") || percategoryNumber.equals("GTIIT_SAS") || percategoryNumber.equals("GTIIT_PSS")){
					if(sickQuota.compareTo(zero)<=0) {
						sickQuota = BigDecimal.valueOf(15);
					}
					highestQuota = BigDecimal.valueOf(75);
				}
				//学术人员教师最高病假额度小于等于0时不限制
				boolean flag = highestQuota.compareTo(zero)>0;
				//平均每月额度
				BigDecimal avgMonthLimit = sickQuota.divide(BigDecimal.valueOf(12),9, BigDecimal.ROUND_HALF_UP);
				//理论每月额度
				BigDecimal theoryMonthLimit = avgMonthLimit.setScale(2, BigDecimal.ROUND_HALF_DOWN);
				//实际授予额度
				BigDecimal realityLimit= theoryMonthLimit;
				//剩余额度
				BigDecimal residueLimit = holidayMap.get(personId)==null?zero:holidayMap.get(personId);
				//标准额度
				BigDecimal standLimit = standLimitMap.get(personId)==null?zero:standLimitMap.get(personId);
				
				//初始额度
				BigDecimal initialLimit = initialMap.get(personId)==null?zero:initialMap.get(personId);
				if(initialLimit.compareTo(highestQuota)>0 && flag) {
					initialLimit = highestQuota;
				}
				
				if(dataCount.compareTo(zero)==0) {
					//本次增减剩余额度和标准额度的天数
					BigDecimal addLimit = initialLimit;
					if(residueLimit.add(initialLimit).compareTo(highestQuota)>0 && flag) {
						addLimit = highestQuota.subtract(residueLimit).subtract(initialLimit).compareTo(zero)<0?zero:highestQuota.subtract(residueLimit).subtract(initialLimit);
					}
					if(residueLimit.compareTo(highestQuota)>0 && flag) {
						addLimit = zero;
					}else if(residueLimit.add(initialLimit).compareTo(highestQuota)>0 && flag) {
						addLimit = highestQuota.subtract(residueLimit);
					}
					
					standLimit = standLimit.add(addLimit);
					residueLimit = residueLimit.add(addLimit);
				}
				//减去当月已授予额度
				BigDecimal deductionsLimit = realityMap.get(personId)==null?zero:realityMap.get(personId);
				standLimit = standLimit.subtract(deductionsLimit);
				residueLimit = residueLimit.subtract(deductionsLimit);
				
				BigDecimal personLeave = leaveLimitMap.get(personId)==null?zero:leaveLimitMap.get(personId);
//				residueLimit = residueLimit.add(personLeave);
				BigDecimal realResidueLimit = residueLimit.add(personLeave);
				
				//计算实际授予额度
				/*if(residueLimit.compareTo(highestQuota)>0 && flag) {
					realityLimit = zero;
				}else if(residueLimit.add(theoryMonthLimit).compareTo(highestQuota)>0 && flag) {
					realityLimit = highestQuota.subtract(residueLimit);
				}*/
				if(realResidueLimit.compareTo(highestQuota)>0 && flag) {
					realityLimit = highestQuota.subtract(realResidueLimit);
				}else if(realResidueLimit.add(theoryMonthLimit).compareTo(highestQuota)>0 && flag) {
					realityLimit = highestQuota.subtract(realResidueLimit);
				}
				
				String HolidayId = personHolidayMap.get(personId)==null?"":personHolidayMap.get(personId);
				//是否已授予
				String isGrant = "0";
				if(isLastDay(nowDate)) {
					isGrant = "1";
					standLimit = standLimit.add(realityLimit);
					residueLimit = residueLimit.add(realityLimit);
				}
				String insertSql = "insert into CT_CUS_SickLeaveLimit(fid,cfmonth,cfpersonid,cfavgmonthlimit,CFTheoryMonthLimit,CFRealityGrantLimit,cfholidayid,CFIsGrant) values(newbosid('5B27CA8D'),'"+dateFormat+"','"+iRowSet.getString("personid")+"','"+avgMonthLimit.toPlainString()+"','"+theoryMonthLimit.toPlainString()+"','"+realityLimit.toPlainString()+"','"+HolidayId+"','"+isGrant+"');";
				strBuffer.append(insertSql);
				
				String uptSql = "update T_HR_ATS_HolidayLimit set FSTANDARDLIMIT = '"+standLimit+"',FREALLIMIT = "+standLimit+"+FADDORSUBLIMIT,FREMAINLIMIT = "+residueLimit+" where fid = '"+HolidayId+"';";
				uptBuffer.append(uptSql);
				
				count++;
				if(count > 3000){
					DbUtil.execute(ctx, strBuffer.toString());
					strBuffer = new StringBuffer();
					DbUtil.execute(ctx, uptBuffer.toString());
					uptBuffer = new StringBuffer();
					count = 0;
				}
			}
			
			if(strBuffer.length()>0){
				DbUtil.execute(ctx, strBuffer.toString());
			}
			if(uptBuffer.length()>0){
				DbUtil.execute(ctx, uptBuffer.toString());
			}
			
		} catch (BOSException e) {
			e.printStackTrace();
		} catch (SQLException throwables) {
			throwables.printStackTrace();
		}
    	
    }
    
    public boolean isLastDay(Date nowDate) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTime(nowDate);
        int currentDate = calendar.get(Calendar.DAY_OF_MONTH);
        int lastDate = calendar.getActualMaximum(Calendar.DATE);
        if (currentDate == lastDate) {
            return true;
        } else {
            return false;
        }
    }
    
    /**
	 * 获取假期类型为对应的假期制度id集合
	 * @param ctx
	 * @param holidayNumber
	 * @return
	 */
	public String getHolidayPolicyIds(Context ctx, String holidayNumber) {
		StringBuffer holidayPolicyIds = new StringBuffer();
		try {
			HolidayTypeCollection holidayTypeCollection = HolidayTypeFactory.getLocalInstance(ctx).getHolidayTypeCollection("where number = '"+holidayNumber+"'");
			if(holidayTypeCollection!=null && holidayTypeCollection.size()>0) {
				HolidayPolicyCollection holidayPolicyCollection = HolidayPolicyFactory.getLocalInstance(ctx).getHolidayPolicyCollection("where holidayType = '"+holidayTypeCollection.get(0).getId().toString()+"'");
				for(int i=0;i<holidayPolicyCollection.size();i++) {
					holidayPolicyIds.append("'"+holidayPolicyCollection.get(i).getId().toString()+"',");
				}
				if(holidayPolicyIds.length()>0) {
					holidayPolicyIds = holidayPolicyIds.deleteCharAt(holidayPolicyIds.length()-1);
				}
			}
		} catch (BOSException e) {
			e.printStackTrace();
		}
		return holidayPolicyIds.toString();
	}
}