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

import com.google.common.collect.Lists;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.util.BOSUuid;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.shr.base.syssetting.app.filter.HRFilterUtils;
import com.kingdee.shr.compensation.SscTypeEnum;
import com.kingdee.shr.compensation.helper.CmpCurrencyHelper;
import com.kingdee.shr.compensation.util.CmpDateUtil;
import com.kingdee.shr.compensation.util.CmpSQLUtil;
import com.kingdee.shr.compensation.util.integrate.CmpIntegrateEntryHelper;
import com.kingdee.shr.compensation.util.integrate.IntegrateEntryTableAttrs;
import com.kingdee.util.LocaleUtils;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SubmitBillEntryFacadeControllerBean extends AbstractSubmitBillEntryFacadeControllerBean {
	private static final long serialVersionUID = -3822503672868646868L;

	private static final Logger logger = LoggerFactory.getLogger(SubmitBillEntryFacadeControllerBean.class);

	private static final String BASE_TABLE_NAME = "T_HR_SchemeBillEntry";

	private static final String ENTITY_TYPE = "7F647776";

	private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

	private String userId;

	protected void _dealSaveEnties(Context ctx, BatchSubmitShemeBillInfo billInfo) throws BOSException, EASBizException {
		String submitSchemeId = billInfo.getSubmitScheme().getId().toString();
		IntegrateEntryTableAttrs entryTableAttrs = CmpIntegrateEntryHelper.getIntegrateEntryTableAttrs(ctx, submitSchemeId);
		List<Object[]> baseParamArrayList = Lists.newArrayList();
		List<Object[]> paramArrayList = Lists.newArrayList();
		BatchSubmitShemeBillEntryCollection coll = billInfo.getEntry();
		for (int i = 0; i < coll.size(); i++)
			assembleSaveParamList(ctx, coll.get(i), billInfo, entryTableAttrs, baseParamArrayList, paramArrayList);
		batchSaveEntries(ctx, billInfo, entryTableAttrs, baseParamArrayList, paramArrayList);
	}

	protected void assembleSaveParamList(Context ctx, BatchSubmitShemeBillEntryInfo entryInfo, BatchSubmitShemeBillInfo billInfo, IntegrateEntryTableAttrs entryTableAttrs, List<Object[]> baseParamArrayList, List<Object[]> paramArrayList) {
		List<Object> paramList = Lists.newArrayList();
		String id = BOSUuid.create("7F647776").toString();
		entryInfo.setId(BOSUuid.read(id));
		paramList.add(id);
		paramList.add(billInfo.getId().toString());
		paramList.add(getUserId(ctx));
		paramList.add(new Timestamp(System.currentTimeMillis()));
		paramList.add(getEffectDate(entryInfo));
		paramList.add((entryInfo.getOrgUnit() == null) ? null : entryInfo.getOrgUnit().getId().toString());
		paramList.add((entryInfo.getPerson() == null) ? null : entryInfo.getPerson().getId().toString());
		paramList.add((entryInfo.getAdminOrgUnit() == null) ? null : entryInfo.getAdminOrgUnit().getId().toString());
		paramList.add((entryInfo.getPosition() == null) ? null : entryInfo.getPosition().getId().toString());
		paramList.add((entryInfo.getCmpEmpORelation() == null) ? null : entryInfo.getCmpEmpORelation().getId().toString());
		paramList.add((entryInfo.getSubmitElement() == null) ? null : entryInfo.getSubmitElement().getId().toString());
		paramList.add((entryInfo.getCurrency() == null) ? CmpCurrencyHelper.getCNYCurrencyId() : entryInfo
				.getCurrency().getId().toString());
		paramList.add(entryInfo.getDescription(LocaleUtils.locale_l1));
		paramList.add(entryInfo.getDescription(LocaleUtils.locale_l2));
		paramList.add(entryInfo.getDescription(LocaleUtils.locale_l3));
		paramList.add((entryInfo.getLeffectDate() == null) ? CmpDateUtil.toSqlDate(CmpDateUtil.getMaxEndDate()) :
				CmpDateUtil.toSqlDate(entryInfo.getLeffectDate()));
		paramList.add(billInfo.getHrOrgUnit().getId().toString());
		paramList.add("01");
		paramList.add(Integer.valueOf(10));
		paramList.add(Integer.valueOf((null == entryInfo.getBillState()) ? 0 : entryInfo
				.getBillState().getValue()));
		if (billInfo.getIsSsc() != SscTypeEnum.DISTRIBUTE) {
			paramList.add(Integer.valueOf(1));
		} else {
			paramList.add(Integer.valueOf((entryInfo.getDealStatus() == null) ? 1 : entryInfo.getDealStatus().getValue()));
		}
		afterAssembleInsertFixColumn(entryInfo, paramList);
		
		// start xiaoxin
		List<Object> baseParamList = Lists.newArrayList(paramList);
		addListValue(baseParamList, entryInfo);
		addListValue(paramList, entryInfo);
		// end
		
		baseParamArrayList.add(baseParamList.toArray());
		assembleDynamicColumn(entryInfo, paramList, entryTableAttrs);
		paramArrayList.add(paramList.toArray());
	}

	private void assembleUpdateParamList(Context ctx, BatchSubmitShemeBillEntryInfo entryInfo, BatchSubmitShemeBillInfo billInfo, IntegrateEntryTableAttrs entryTableAttrs, List<Object[]> baseParamArrayList, List<Object[]> paramArrayList) {
		List<Object> updateParamList = Lists.newArrayList();
		updateParamList.add(getUserId(ctx));
		updateParamList.add(new Timestamp(System.currentTimeMillis()));
		updateParamList.add(getEffectDate(entryInfo));
		updateParamList.add((entryInfo.getOrgUnit() == null) ? null : entryInfo.getOrgUnit().getId().toString());
		updateParamList.add((entryInfo.getPerson() == null) ? null : entryInfo.getPerson().getId().toString());
		updateParamList.add((entryInfo.getAdminOrgUnit() == null) ? null : entryInfo.getAdminOrgUnit().getId().toString());
		updateParamList.add((entryInfo.getPosition() == null) ? null : entryInfo.getPosition().getId().toString());
		updateParamList.add((entryInfo.getCmpEmpORelation() == null) ? null : entryInfo.getCmpEmpORelation().getId().toString());
		updateParamList.add((entryInfo.getSubmitElement() == null) ? null : entryInfo.getSubmitElement().getId().toString());
		updateParamList.add((entryInfo.getCurrency() == null) ? CmpCurrencyHelper.getCNYCurrencyId() : entryInfo.getCurrency().getId().toString());
		updateParamList.add(entryInfo.getDescription(LocaleUtils.locale_l1));
		updateParamList.add(entryInfo.getDescription(LocaleUtils.locale_l2));
		updateParamList.add(entryInfo.getDescription(LocaleUtils.locale_l3));
		updateParamList.add((entryInfo.getLeffectDate() == null) ?
				CmpDateUtil.toSqlDate(CmpDateUtil.getMaxEndDate()) : entryInfo.getLeffectDate());
		if (billInfo.getIsSsc() != SscTypeEnum.DISTRIBUTE) {
			updateParamList.add(Integer.valueOf(1));
		} else {
			updateParamList.add(Integer.valueOf((entryInfo.getDealStatus() == null) ? 1 : entryInfo.getDealStatus().getValue()));
		}

		afterAssembleUpdateFixColumn(entryInfo, updateParamList);
		List<Object> updateBaseParamList = Lists.newArrayList(updateParamList);

		// start xiaoxin
		addListValue(updateBaseParamList, entryInfo);
		addListValue(updateParamList, entryInfo);
		// end

		updateBaseParamList.add(entryInfo.getId().toString());
		baseParamArrayList.add(updateBaseParamList.toArray());
		assembleDynamicColumn(entryInfo, updateParamList, entryTableAttrs);
		updateParamList.add(entryInfo.getId().toString());
		paramArrayList.add(updateParamList.toArray());
	}

	protected Date getEffectDate(BatchSubmitShemeBillEntryInfo entryInfo) {
		Date effectDate = entryInfo.getEffectDate();
		if (effectDate != null)
			return CmpDateUtil.toSqlDate(effectDate);
		return CmpDateUtil.toSqlDate(entryInfo.get("effectday"));
	}

	protected void assembleDynamicColumn(BatchSubmitShemeBillEntryInfo entryInfo, List<Object> paramList, IntegrateEntryTableAttrs entryTableAttrs) {
		int index = 0;
		for (String colName : entryTableAttrs.getColNames()) {
			String dataType = entryTableAttrs.getColTypes().get(index++);
			int dataLength = ((Integer)entryTableAttrs.getDataLength().get(colName)).intValue();
			Object object = entryInfo.get(colName);
			if (object != null && object.toString().trim().length() > 0 && "2"
					.equals(dataType)) {
				String datestr = object.toString();
				try {
					Date date = this.dateFormat.parse(datestr);
					paramList.add(new Date(date.getTime()));
				} catch (ParseException e) {
					logger.error(e.getMessage(), e);
					paramList.add(null);
				}
				continue;
			}
			if (object != null && object.toString().trim().length() > 0 && "1"
					.equals(dataType) && object.toString().length() > dataLength) {
				paramList.add(object.toString().substring(0, dataLength));
				continue;
			}
			paramList.add("0E-10".equals(object) ? "0.00" : object);
		}
	}

	protected void _saveOrUpdateEntries(Context ctx, BatchSubmitShemeBillInfo billInfo) throws BOSException, EASBizException {
		String submitSchemeId = billInfo.getSubmitScheme().getId().toString();
		IntegrateEntryTableAttrs entryTableAttrs = CmpIntegrateEntryHelper.getIntegrateEntryTableAttrs(ctx, submitSchemeId);
		BatchSubmitShemeBillEntryCollection coll = billInfo.getEntry();
		List<Object[]> updateBaseParamArrayList = Lists.newArrayList();
		List<Object[]> updateParamArrayList = Lists.newArrayList();
		List<Object[]> insertBaseParamArrayInsertList = Lists.newArrayList();
		List<Object[]> insertParamArrayList = Lists.newArrayList();
		for (int i = 0; i < coll.size(); i++) {
			BatchSubmitShemeBillEntryInfo entryInfo = coll.get(i);
			if (entryInfo.getId() != null) {
				assembleUpdateParamList(ctx, entryInfo, billInfo, entryTableAttrs, updateBaseParamArrayList, updateParamArrayList);
			} else {
				assembleSaveParamList(ctx, entryInfo, billInfo, entryTableAttrs, insertBaseParamArrayInsertList, insertParamArrayList);
			}
		}
		batchUpdateEntries(ctx, billInfo, entryTableAttrs, updateBaseParamArrayList, updateParamArrayList);
		batchSaveEntries(ctx, billInfo, entryTableAttrs, insertBaseParamArrayInsertList, insertParamArrayList);
	}

	protected void batchSaveEntries(Context ctx, BatchSubmitShemeBillInfo billInfo, IntegrateEntryTableAttrs entryTableAttrs, List<Object[]> baseParamArrayList, List<Object[]> paramArrayList) throws BOSException {
		if (!paramArrayList.isEmpty()) {
			String insertBaseSql = getInsertBaseEntryPrepareSql();
			String insertSql = getInsertEntryPrepareSql(entryTableAttrs.getTableName(), entryTableAttrs.getColNames(), false);
			CmpSQLUtil.executeBatch(ctx, insertBaseSql, baseParamArrayList);
			CmpSQLUtil.executeBatch(ctx, insertSql, paramArrayList);
		}
	}

	protected void batchUpdateEntries(Context ctx, BatchSubmitShemeBillInfo billInfo, IntegrateEntryTableAttrs entryTableAttrs, List<Object[]> baseParamArrayList, List<Object[]> paramArrayList) throws BOSException, EASBizException {
		if (!paramArrayList.isEmpty()) {
			String updateBaseSql = getUpdateBaseSql();
			String updateSql = getUpdateSql(entryTableAttrs.getTableName(), entryTableAttrs.getColNames(), false);
			CmpSQLUtil.executeBatch(ctx, updateBaseSql, baseParamArrayList);
			CmpSQLUtil.executeBatch(ctx, updateSql, paramArrayList);
		}
	}

	protected List<String> getInsertFixColumnNames() {
		return Lists.newArrayList(new String[] {
				"FID", "FBillID", "FCreatorID", "FCreateTime", "FEffectDate", "FOrgUnitID", "FPersonID", "FAdminOrgUnitID", "FPositionID", "FCmpEmpORelationID",
				"FSubmitElementID", "FCurrencyID", "FDescription_l1", "FDescription_l2", "FDescription_l3", "FLeffectDate", "FHrOrgUnitID", "FCalState", "FIsCal", "FBillState",
				"FDealStatus" });
	}

	protected void afterAssembleInsertFixColumn(BatchSubmitShemeBillEntryInfo entryInfo, List<Object> paramList) {}

	protected List<String> getUpdateFixColumnNames() {
		return Lists.newArrayList(new String[] {
				"FLastUpdateUserID", "FLastUpdateTime", "FEffectDate", "FOrgUnitID", "FPersonID", "FAdminOrgUnitID", "FPositionID", "FCmpEmpORelationID", "FSubmitElementID", "FCurrencyID",
				"FDescription_l1", "FDescription_l2", "FDescription_l3", "FLeffectDate", "FDealStatus" });
	}

	protected void afterAssembleUpdateFixColumn(BatchSubmitShemeBillEntryInfo entryInfo, List<Object> paramList) {}

	protected String getInsertBaseEntryPrepareSql() {
		return getInsertEntryPrepareSql(null, null, true);
	}

	protected String getInsertEntryPrepareSql(String dynamicEntryTable, List<String> submitItemColumnNames, boolean isBase) {
		String entryTableName, submitItemKeys = "";
		String submitItemvalues = "";
		if (isBase) {
			entryTableName = "T_HR_SchemeBillEntry";
		} else {
			entryTableName = dynamicEntryTable;
			submitItemKeys = "," + StringUtils.join(submitItemColumnNames, ",");
			submitItemvalues = submitItemKeys.replaceAll("[Ss]{1}\\d{1,4}", "?");
		}
		List<String> fixColumnNames = getInsertFixColumnNames();

		// start xiaoxin
		//if(isBase){
			addListParam(fixColumnNames);
		//}
		// end

		String fixColumnKeys = StringUtils.join(fixColumnNames, ",");
		String fixColumnValues = fixColumnKeys.replaceAll("\\w+", "?");
		return "INSERT INTO " + entryTableName + " (" + fixColumnKeys + submitItemKeys + ") VALUES (" + fixColumnValues + submitItemvalues + ")";
	}

	protected String getUpdateBaseSql() {
		return getUpdateSql(null, null, true);
	}

	protected String getUpdateSql(String dynamicEntryTable, List<String> submitItemColumnNames, boolean isBase) {
		String entryTableName;
		if (isBase) {
			entryTableName = "T_HR_SchemeBillEntry";
		} else {
			entryTableName = dynamicEntryTable;
		}
		StringBuilder updateSql = new StringBuilder("UPDATE %s SET ");
		List<String> updateColumnNames = getUpdateFixColumnNames();
		
		// start xiaoxin
		//if(isBase){
			addListParam(updateColumnNames);
		//}
		// end
			
		if (submitItemColumnNames != null) {
			updateColumnNames.addAll(submitItemColumnNames);
		}

		List<String> setSqlColumnList = Lists.newArrayList();
		for (String columnName : updateColumnNames) {
			setSqlColumnList.add(columnName + "=?");
		}
		updateSql.append(StringUtils.join(setSqlColumnList.toArray(), ","));
		updateSql.append(" WHERE fid=?");
		return String.format(updateSql.toString(), new Object[] { entryTableName });
	}

	protected String getUserId(Context ctx) {
		if (this.userId == null)
			this.userId = HRFilterUtils.getCurrentUserId(ctx);
		return this.userId;
	}

	/**
	 * 添加自定义字段
	 * @param list
	 */
	protected void addListParam(List<String> list) {
		//直属上级ID
		list.add("CFSuperiorID");
		//直属上级名称
		list.add("CFSuperiorName");
		//时薪
		list.add("cfhourlyWage");
		//开始时间
		list.add("cfstartTime");
		//结束时间
		list.add("cfendTime");
		//休息开始时间
		list.add("cfrestStartTime");
		//休息结束时间
		list.add("cfrestEndTime");
		//说明
		list.add("cfexplain");
		//总工时
		list.add("cftotalWorkHours");
		//总金额
		list.add("cftotalAmount");
		//合同开始日期
		list.add("CFBeginContractDate");
		//合同结束日期
		list.add("CFEndContractDate");
		//备注
		list.add("CFRemark");
	}

	/**
	 * 给自定义字段赋值
	 * @param list
	 * @param entryInfo
	 */
	protected void addListValue(List<Object> list, BatchSubmitShemeBillEntryInfo entryInfo) {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//		if(entryInfo.get("superiorId")!=null) {
//			list.add(((PersonInfo)entryInfo.get("superior")).getId().toString());
//		}else {
//			list.add("");
//		} 
		//直属上级ID
		list.add(entryInfo.getString("superiorId"));
		//直属上级名称
		list.add(entryInfo.getString("superiorName"));
		//时薪
		list.add(entryInfo.get("hourlyWage"));
//		list.add(sdf.format(entryInfo.getDate("startTime")));
//		list.add(sdf.format(entryInfo.getDate("endTime")));
		//开始时间 -- 格式化成字符串保存，避免只保存年月日
		if(StringUtils.isNotBlank(entryInfo.getString("startTime"))) {
			list.add(sdf.format(entryInfo.getDate("startTime")));
		}else {
			list.add(null);
		}
		//结束时间
		if(StringUtils.isNotBlank(entryInfo.getString("endTime"))) {
			list.add(sdf.format(entryInfo.getDate("endTime")));
		}else {
			list.add(null);
		}
		//休息开始时间
		if(StringUtils.isNotBlank(entryInfo.getString("restStartTime"))) {
			list.add(sdf.format(entryInfo.getDate("restStartTime")));
		}else {
			list.add(null);
		}
		//休息结束时间
		if(StringUtils.isNotBlank(entryInfo.getString("restEndTime"))) {
			list.add(sdf.format(entryInfo.getDate("restEndTime")));
		}else {
			list.add(null);
		}
		//说明
		list.add(entryInfo.getString("explain"));
		//总工时
		list.add(entryInfo.get("totalWorkHours"));
		//总金额
		list.add(entryInfo.get("totalAmount"));
		//合同开始日期
		if(StringUtils.isNotBlank(entryInfo.getString("beginContractDate"))) {
			list.add(sdf.format(entryInfo.getDate("beginContractDate")));
		}else {
			list.add(null);
		}
		//合同结束日期
		if(StringUtils.isNotBlank(entryInfo.getString("endContractDate"))) {
			list.add(sdf.format(entryInfo.getDate("endContractDate")));
		}else {
			list.add(null);
		}
		//备注
		list.add(entryInfo.getString("remark"));
	}
}
