package com.kingdee.shr.compensation.integrate.verify;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.dao.ormapping.ObjectUuidPK;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.utils.DateTimeUtils;
import com.kingdee.eas.framework.CoreBaseInfo;
import com.kingdee.eas.hr.base.HRBillStateEnum;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.compensation.app.entity.Pair;
import com.kingdee.shr.compensation.app.integrate.BatchSubmitShemeBillCollection;
import com.kingdee.shr.compensation.app.integrate.BatchSubmitShemeBillEntryCollection;
import com.kingdee.shr.compensation.app.integrate.BatchSubmitShemeBillEntryInfo;
import com.kingdee.shr.compensation.app.integrate.BatchSubmitShemeBillFactory;
import com.kingdee.shr.compensation.app.integrate.BatchSubmitShemeBillInfo;
import com.kingdee.shr.compensation.app.integrate.CalSubmitSchemeCollection;
import com.kingdee.shr.compensation.app.integrate.CalSubmitSchemeFactory;
import com.kingdee.shr.compensation.app.integrate.DateTypeEnum;
import com.kingdee.shr.compensation.exception.SubmitBillVerifyException;
import com.kingdee.shr.compensation.integrate.verify.ISubmitBillVerifyInterface;
import com.kingdee.shr.compensation.util.CmpDateUtil;
import com.kingdee.shr.compensation.util.db.CmpInSql;
import com.kingdee.shr.compensation.util.db.CmpInSqlFactory;
import com.kingdee.shr.compensation.util.integrate.CmpIntegrateEntryHelper;
import com.kingdee.shr.ml.util.SHRServerResource;
import com.kingdee.util.LocaleUtils;
import java.sql.SQLException;
import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

public abstract class AbstractSubmitBillVerify implements ISubmitBillVerifyInterface {
	
	private static Logger logger =
	        Logger.getLogger("com.kingdee.shr.compensation.integrate.verify.AbstractSubmitBillVerify");
	
	public void verify(Context ctx, CoreBaseInfo model, Map<String, Object> otherParams) throws BOSException, EASBizException {
		beforeVerify(ctx, model, otherParams);
		runVerify(ctx, model, otherParams);
		afterVerify(ctx, model, otherParams);
	}

	protected void beforeVerify(Context ctx, CoreBaseInfo model, Map<String, Object> otherParams) throws BOSException, EASBizException {
		BatchSubmitShemeBillInfo info = (BatchSubmitShemeBillInfo)model;
		checkBillNumber(ctx, info);
		verifyBillState(ctx, (CoreBaseInfo)info);
	}

	protected void verifyBillState(Context ctx, CoreBaseInfo model) throws EASBizException, BOSException {
		BatchSubmitShemeBillInfo info = (BatchSubmitShemeBillInfo)model;
		BatchSubmitShemeBillCollection colsInDB = BatchSubmitShemeBillFactory.getLocalInstance(ctx).getBatchSubmitShemeBillCollection("select billState where id = '" + info.getId().toString() + "'");
		if (colsInDB.isEmpty())
			return;
		HRBillStateEnum billState = colsInDB.get(0).getBillState();
		if (HRBillStateEnum.SAVED != billState && HRBillStateEnum.SUBMITED != billState)
			throw new SubmitBillVerifyException(SubmitBillVerifyException.EXCEPTION4);
	}

	protected void runVerify(Context ctx, CoreBaseInfo model, Map<String, Object> otherParams) throws BOSException, EASBizException {
		BatchSubmitShemeBillInfo info = (BatchSubmitShemeBillInfo)model;
		verifyRemovedCmpFile(ctx, info);
		verifyCmpEmpRe(ctx, info);
		verifySubmitPeriod(ctx, info);
	}

	protected void verifyRemovedCmpFile(Context ctx, BatchSubmitShemeBillInfo info) throws BOSException, EASBizException {
		String billEntryTable = CmpIntegrateEntryHelper.getIntegrateDynamicEntryTableNameBySubmitSchemeId(ctx, info.getSubmitScheme().getId().toString());
		String sqlTemplate = "SELECT entry.fpersonId, person.FName_%s personName, person.FNumber personNum FROM %s entry LEFT JOIN T_BD_PERSON person ON entry.FPersonId = person.Fid WHERE NOT EXISTS(SELECT 1 FROM T_HR_SCmpEmpORelation empOrel WHERE entry.FCmpEmpORelationID = empOrel.FID) AND entry.fbillId = '%s'";
		Set<String> nameAndNumSet = new HashSet<>();
		String personHint = SHRServerResource.getString("com.kingdee.shr.compensation.resource.CommonResource", "label195", ctx.getLocale());
		try {
			IRowSet rs = DbUtil.executeQuery(ctx, String.format(sqlTemplate, new Object[] { LocaleUtils.getShortCode(ctx.getLocale()), billEntryTable, info
					.getId().toString() }));
			while (rs.next()) {
				nameAndNumSet.add(MessageFormat.format(personHint, new Object[] { rs.getString("personName"), rs.getString("personNum") }));
			}
		} catch (SQLException e) {
			throw new BOSException(e.getMessage(), e);
		}
		if (!nameAndNumSet.isEmpty())
			throw new SubmitBillVerifyException(SubmitBillVerifyException.EXCEPTION1, nameAndNumSet.toArray());
	}

	protected void afterVerify(Context ctx, CoreBaseInfo model, Map<String, Object> otherParams) throws BOSException {}

	protected void verifyCmpEmpRe(Context ctx, BatchSubmitShemeBillInfo info) throws BOSException, EASBizException {
		Map<String, Pair<Date, Date>> empCmpRelationsFromDb = getEmpCmpRelationsFromDb(ctx, info);
		
		if (empCmpRelationsFromDb.isEmpty())
			return;
		Set<String> errorPersons = new HashSet<>();
		DateTypeEnum effectDateDisplay = null;
		CalSubmitSchemeCollection submitScheme = CalSubmitSchemeFactory.getLocalInstance(ctx).getCalSubmitSchemeCollection("where id = '" + info.getSubmitScheme().getId().toString() + "'");
		if (submitScheme != null && submitScheme.size() > 0)
			effectDateDisplay = submitScheme.get(0).getEffectDateDisplay();
		BatchSubmitShemeBillEntryCollection coll = info.getEntry();
		
		int adjustMonth = 0;
		Set<String> personSet = new HashSet<>();
		int dataSource = info.getDatasource().getValue();
		if(dataSource == 2) {
			Set<String> personIdSet = new HashSet<>();
			for (int i = 0; i < coll.size(); i++) {
				BatchSubmitShemeBillEntryInfo entryInfo = coll.get(i);
				String personId = entryInfo.getPerson().getId().toString();
				personIdSet.add(personId);
			}
			logger.error("人员ID集合："+personIdSet);
			StringBuffer personIds = new StringBuffer();
			for(String id:personIdSet) {
				personIds.append("'"+id+"',");
			}
			
			String sql = "select top 1 * from T_HR_SHRRsvItem0 where fnumber = '1005' and FState = '1'";
			//调整月份
			try {
				IRowSet rs = DbUtil.executeQuery(ctx, sql);
				while(rs.next()) {
					adjustMonth = rs.getInt("FName_l2");
				}
				if(personIds.length()>0) {
					personIds.deleteCharAt(personIds.length()-1);
					String nowDate = DateTimeUtils.dateFormat(new Date(), "yyyy-MM-dd");
					String personSql = "SELECT DISTINCT a.fpersonid,a.fpositionid FROM T_HR_EmpOrgRelation a "
							+ "left join T_HR_EmpLaborRelationHis b on a.FPERSONID=b.fpersonid "
							+ "left join T_HR_BDEmployeeType c on c.fid=b.flaborrelationstateid "
							+ "where c.finservice not in ('2','3') and a.feffdt <= '"+nowDate+"' "
							+ "and a.fleffdt >= '"+nowDate+"' and a.fislatestinaday = '1' "
							+ "and b.fstartdatetime <= '"+nowDate+"' and b.fenddatetime >= '"+nowDate+"' "
							+ "and a.fpersonid in ("+personIds+")";
					logger.error("查询在职人员SQL："+personSql);
					IRowSet personRow = DbUtil.executeQuery(ctx, personSql);
					while(personRow.next()) {
						personSet.add(personRow.getString("fpersonid")+ "_" + personRow.getString("fpositionid"));
					}
					logger.error("员工+部门ID集合"+personSet);
				}
			} catch (BOSException e) {
				e.printStackTrace();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		
		if (coll != null && coll.size() > 0)
			for (int i = 0; i < coll.size(); i++) {
				BatchSubmitShemeBillEntryInfo entryInfo = coll.get(i);
				String employeeTypeId = entryInfo.getCmpEmpORelation().getId().toString();
				Date entryDate = entryInfo.getEffectDate();
				String personId = entryInfo.getPerson().getId().toString();
				String positionId = entryInfo.getPosition().getId().toString();
				
				//校验发生日期时根据调整月份进行调整(只针对离职员工)
				if(!personSet.contains(personId+"_"+positionId)) {
					Calendar calendar = Calendar.getInstance();
					calendar.setTime(entryDate);
					calendar.add(Calendar.MONTH, adjustMonth);
					entryDate = calendar.getTime();
				}
				
				Pair<Date, Date> pair = empCmpRelationsFromDb.get(personId + "_" + positionId + "_" + employeeTypeId);
				if (null != pair) {
					Date effectDate = (Date)pair.getFirst();
					Date leffectDate = (Date)pair.getSecond();
					String personName = getPersonNameIfVerified(entryInfo);
					if (effectDateDisplay == DateTypeEnum.yyyyMM) {
						if (CmpDateUtil.compareMonth(entryDate, effectDate) < 0 || CmpDateUtil.compareMonth(entryDate, leffectDate) > 0)
							errorPersons.add(personName);
					} else if (entryDate.compareTo(effectDate) < 0 || entryDate.compareTo(leffectDate) > 0) {
						errorPersons.add(personName);
					}
				}
			}
		int maxSize = 30;
		int size = 1;
		StringBuilder errorMessage = new StringBuilder();
		for (String errorPersonName : errorPersons) {
			if (maxSize <= size)
				break;
			errorMessage.append(errorPersonName).append("、");
					size++;
		}
		if (errorMessage.length() > 0) {
			String message = errorMessage.substring(0, errorMessage.length() - 1);
			if (size == maxSize)
				message = message + "...";
			throw new SubmitBillVerifyException(SubmitBillVerifyException.EXCEPTION5, new Object[] { message });
		}
	}

	protected String getPersonNameIfVerified(BatchSubmitShemeBillEntryInfo entryInfo) throws EASBizException {
		String personName = entryInfo.getPerson().getName();
		if (StringUtils.isEmpty(personName))
			throw new SubmitBillVerifyException(SubmitBillVerifyException.PERSON_PERM_ERROR);
		return personName;
	}

	protected Map<String, Pair<Date, Date>> getEmpCmpRelationsFromDb(Context ctx, BatchSubmitShemeBillInfo info) throws BOSException, EASBizException {
		BatchSubmitShemeBillEntryCollection coll = info.getEntry();
		Set<String> personIds = new HashSet<>();
		boolean personIsNull = false;
		for (int i = 0; i < coll.size(); i++) {
			if (coll.get(i).getPerson() == null || coll.get(i).getPerson().getId() == null) {
				personIsNull = true;
			} else {
				personIds.add(coll.get(i).getPerson().getId().toString());
			}
		}
		if (personIsNull) {
			throw new SubmitBillVerifyException(SubmitBillVerifyException.EXCEPTION8);
		}
		CmpInSql<String> cmpInSql = CmpInSqlFactory.getInstance();
		String personInSql = cmpInSql.createInSqlBaseOnFId(ctx, personIds);
		String hrOrgUnitId = info.getHrOrgUnit().getId().toString();
		String adminOrgId = info.getAdminOrg().getId().toString();
		String longNumber = getLongNumber(ctx, adminOrgId);
		StringBuilder filter = new StringBuilder();
		String sql = "select p.Fid personId, p.FNumber, ce.FEffectDate, ce.FLeffectDate, pt.Fid positionId,ce.Fid employeeTypeId  FROM T_HR_SCmpEmpORelation AS ce  INNER JOIN T_HR_SPersonCmp AS pc ON ce.FPersonCmpID = pc.FID  INNER JOIN T_HR_EmpOrgRelation AS er ON ce.FEmpOrgRelationID = er.FID  INNER JOIN T_BD_Person AS p ON ce.FPersonID = p.FID  INNER JOIN T_ORG_HRO AS h ON pc.FHrOrgUnitID = h.FID  LEFT OUTER JOIN T_ORG_Admin AS ad ON er.FAdminOrgID = ad.FID  LEFT OUTER JOIN T_ORG_Position AS pt ON er.FPositionID = pt.FID LEFT OUTER JOIN T_HR_EmpLaborRelationHis AS re ON er.FlaborRelationID =re.FHistoryRelateID and er.FEndDateTime >=re.FStartDateTime and er.FEndDateTime <=re.FEndDateTime LEFT OUTER JOIN T_HR_BDEmployeeType AS et ON re.FLaborRelationStateID =et.FID ";
		filter.append(sql);
		filter.append(" where h.FID = '").append(hrOrgUnitId).append("'");
		filter.append(" and ((ad.flongNumber LIKE '").append(longNumber).append("%' and ce.fuseDefault=1) or ce.fuseDefault=0)");
		filter.append(" and p.FID in").append(personInSql);
		Map<String, Pair<Date, Date>> dbMap = new HashMap<>();
		try {
			IRowSet rs = DbUtil.executeQuery(ctx, filter.toString());
			while (rs.next()) {
				Pair<Date, Date> pair = new Pair();
				Date effectDate = rs.getDate("FEffectDate");
				Date leffectDate = rs.getDate("FLeffectDate");
				pair.setFirst(effectDate);
				pair.setSecond(leffectDate);
				String personIdDB = rs.getString("personId");
				String positionIdDB = rs.getString("positionId");
				String employeeTypeId = rs.getString("employeeTypeId");
				dbMap.put(personIdDB + "_" + positionIdDB + "_" + employeeTypeId, pair);
			}
		} catch (SQLException e) {
			throw new BOSException(e.getMessage(), e);
		}
		cmpInSql.release(ctx);
		return dbMap;
	}

	protected String getLongNumber(Context ctx, String id) throws BOSException {
		String sql = "select FLongNumber from T_ORG_Admin where fid = '" + id + "'";
		String longNumber = "";
		try {
			IRowSet rs = DbUtil.executeQuery(ctx, sql);
			while (rs.next())
				longNumber = rs.getString("FLongNumber");
		} catch (SQLException e) {
			throw new BOSException(e.getMessage(), e);
		}
		return longNumber;
	}

	protected void checkBillNumber(Context ctx, BatchSubmitShemeBillInfo info) throws BOSException, EASBizException {
		String number = info.getNumber();
		boolean flag = BatchSubmitShemeBillFactory.getLocalInstance(ctx).exists("where number = '" + number + "' and id <> '" + info
				.getId().toString() + "'");
		if (flag)
			throw new SubmitBillVerifyException(SubmitBillVerifyException.EXCEPTION6, new Object[] { number });
	}

	protected void verifySubmitPeriod(Context ctx, BatchSubmitShemeBillInfo info) throws EASBizException, BOSException {}

	protected String getMultiLan(Context ctx, String label) {
		return SHRServerResource.getString("com.kingdee.shr.compensation.resource.SubmitShemeBillResource", label, ctx.getLocale());
	}
}
