package com.kingdee.eas.custom.hireapproval.task;

import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.metadata.entity.*;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.bos.util.BOSUuid;
import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
import com.kingdee.eas.basedata.org.HROrgUnitInfo;
import com.kingdee.eas.basedata.org.PositionInfo;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.hireapproval.*;
import com.kingdee.eas.custom.hireapproval.bizEnum.ExecuteStateEnum;
import com.kingdee.eas.hr.base.EmpLaborRelationCollection;
import com.kingdee.eas.hr.base.EmpLaborRelationFactory;
import com.kingdee.eas.hr.base.EmpLaborRelationInfo;
import com.kingdee.eas.hr.base.IEmpLaborRelation;
import com.kingdee.eas.hr.emp.IPersonPosition;
import com.kingdee.eas.hr.emp.PersonPositionCollection;
import com.kingdee.eas.hr.emp.PersonPositionFactory;
import com.kingdee.eas.hr.emp.PersonPositionInfo;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.eas.utils.StringExUtils;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.cmpdesign.app.v2.base.AdjustSalaryItemInfo;
import com.kingdee.shr.cmpdesign.app.v2.bill.*;
import com.kingdee.shr.compensation.AdjustEmpORelationCollection;
import com.kingdee.shr.compensation.AdjustEmpORelationFactory;
import com.kingdee.shr.compensation.AdjustEmpORelationInfo;
import com.kingdee.shr.compensation.IAdjustEmpORelation;
import com.kingdee.shr.compensation.app.integrate.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.math.BigDecimal;
import java.util.*;

public class HireApprovalFacadeControllerBean extends AbstractHireApprovalFacadeControllerBean {
    private static Logger logger = Logger.getLogger(HireApprovalFacadeControllerBean.class);
    private final String CALSUBMITSCHEMENUMBER = "002";//提报方案(定调薪方案)

    /**
     * 自动生成入职定薪单
     *
     * @param ctx
     * @param billIds 单据id
     * @throws BOSException
     * @throws EASBizException
     */
    @Override
    protected void _createHireSalaryBill(
            Context ctx,
            String billIds
    ) throws BOSException, EASBizException {
        super._createHireSalaryBill(ctx, billIds);
        SelectorItemCollection sic = new SelectorItemCollection();
        sic.add("*");
        sic.add("entrys.*");
        sic.add("entrys.cmpItem.*");
        FilterInfo filterInfo = new FilterInfo();
        FilterItemCollection filterItems = filterInfo.getFilterItems();
        if (StringUtils.isNotBlank(billIds)) {
            if (billIds.contains("'")) {
                billIds = billIds.replace("'", "");
            }
            //执行状态为未执行/失败
            filterItems.add(new FilterItemInfo("executeStatus", "0,2", CompareType.INCLUDE));
            filterItems.add(new FilterItemInfo("id", billIds, CompareType.INCLUDE));
        } else {
            //执行状态为未执行
            filterItems.add(new FilterItemInfo("executeStatus", "0"));
        }
        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
        logger.error("_createHireSalaryBill viewInfo.encode(): " + viewInfo.encode());
        IOAHireSalaryData ioaHireSalaryData = OAHireSalaryDataFactory.getLocalInstance(ctx);
        OAHireSalaryDataCollection oaHireSalaryDataCol = ioaHireSalaryData.getOAHireSalaryDataCollection(viewInfo);
        if (oaHireSalaryDataCol.isEmpty()) {
            logger.error("没有获取到OA录用定薪数据");
        }
        //获取定调薪提报方案
        CalSubmitSchemeInfo calSubmitSchemeInfo = getCalSubmitSchemeInfo(ctx);
        //薪酬项目与定薪项目表字段
        String adjustSalaryRuleId = calSubmitSchemeInfo.getId().toString();
        Map<String, String> adjItem2CmpItem = getAdjItem2CmpItem(ctx, adjustSalaryRuleId);
        SelectorItemCollection updateSic = new SelectorItemCollection();
        updateSic.add("executeStatus");
        updateSic.add("executeResult");
        for (int i = 0; i < oaHireSalaryDataCol.size(); i++) {
            OAHireSalaryDataInfo oaHireSalaryDataInfo = oaHireSalaryDataCol.get(i);
            try {
                generateAdjustSalaryApply(ctx, oaHireSalaryDataInfo, calSubmitSchemeInfo, adjItem2CmpItem);
            } catch (Exception e) {
                logger.error(e.getMessage());
                oaHireSalaryDataInfo.setExecuteStatus(ExecuteStateEnum.ERROR);
                oaHireSalaryDataInfo.setExecuteResult(e.getMessage());
            }
            ioaHireSalaryData.updatePartial(oaHireSalaryDataInfo, updateSic);
        }
    }

    /**
     * @param ctx
     * @param dataInfo
     * @param calSubmitSchemeInfo
     * @param adjItem2CmpItem
     * @throws BOSException
     */
    private void generateAdjustSalaryApply(
            Context ctx,
            OAHireSalaryDataInfo dataInfo,
            CalSubmitSchemeInfo calSubmitSchemeInfo,
            Map<String, String> adjItem2CmpItem
    ) throws BOSException, EASBizException {
        IAdjustSalaryApply iAdjustSalaryApply = AdjustSalaryApplyFactory.getLocalInstance(ctx);
        IAdjustSalaryApplyEntry iAdjustSalaryApplyEntry = AdjustSalaryApplyEntryFactory.getLocalInstance(ctx);
        IOAHireSalaryData ioaHireSalaryData = OAHireSalaryDataFactory.getLocalInstance(ctx);
        String id = dataInfo.getId().toString();
        boolean canExecute = ioaHireSalaryData.isCanExecute(id);
        if (!canExecute) {
            return;
        }
        //设置执行状态为执行中
        ioaHireSalaryData.setExecuting(id);
        //OA录用定薪数据
        OAHireSalaryDataEntryCollection entrys = dataInfo.getEntrys();
        String passport = dataInfo.getPassport();
        String idNumber = dataInfo.getIdNumber();
        if (!StringExUtils.isAnyNotEmpty(idNumber, passport)) {
            throw new BOSException("身份证号码和其他证件号不能全为空!");
        }
        IPersonPosition iPersonPosition = PersonPositionFactory.getLocalInstance(ctx);
        PersonPositionCollection personPositionCol = iPersonPosition.getPersonPositionCollection("select *,person.name where person.passportNO='" + passport + "' or person.idCardNO='" + idNumber + "'");
        if (personPositionCol.isEmpty()) {
            logger.error("generateAdjustSalaryApply 没有匹配到身份证[" + idNumber + "]或其他证件号[" + passport + "]的在职员工");
            dataInfo.setExecuteStatus(ExecuteStateEnum.UNEXECUTE);
            dataInfo.setExecuteResult("没有匹配到身份证[" + idNumber + "]或其他证件号[" + passport + "]的在职员工");
            return;
        }
        if (personPositionCol.size() > 1) {
            logger.error("generateAdjustSalaryApply 没有匹配到身份证[" + idNumber + "]或其他证件号[" + passport + "]的在职员工");
            throw new BOSException("匹配到多个身份证[" + idNumber + "]或其他证件号[" + passport + "]的在职员工");
        }
        PersonPositionInfo personPositionInfo = personPositionCol.get(0);
        PersonInfo person = personPositionInfo.getPerson();//人员
        String personName = person.getName();
        AdminOrgUnitInfo personDep = personPositionInfo.getPersonDep();//部门
        PositionInfo primaryPosition = personPositionInfo.getPrimaryPosition();//职位
        //校验定调薪档案是否存在
        IAdjustEmpORelation iAdjustEmpORelation = AdjustEmpORelationFactory.getLocalInstance(ctx);
        AdjustEmpORelationCollection adjustEmpORelationCol = iAdjustEmpORelation.getAdjustEmpORelationCollection("where person='" + person.getId() + "' order by leffectDate desc");
        if (adjustEmpORelationCol.isEmpty()) {
            logger.error("generateAdjustSalaryApply 没有匹配到对应的定薪档案任职信息");
            dataInfo.setExecuteStatus(ExecuteStateEnum.UNEXECUTE);
            dataInfo.setExecuteResult("没有匹配到对应的定薪档案任职信息");
            return;
        }
        AdjustEmpORelationInfo adjustEmpORelationInfo = adjustEmpORelationCol.get(0);
        //获取入职日期
        IEmpLaborRelation iEmpLaborRelation = EmpLaborRelationFactory.getLocalInstance(ctx);
        EmpLaborRelationCollection empLaborRelationCol =
                iEmpLaborRelation.getEmpLaborRelationCollection("where person='" + person.getId() + "'");
        if (empLaborRelationCol.isEmpty()) {
            throw new BOSException("没找到员工[" + personName + "]的用工关系记录");
        }
        EmpLaborRelationInfo empLaborRelationInfo = empLaborRelationCol.get(0);
        Date enterDate = empLaborRelationInfo.getEnterDate();
        //判断定薪单是否存在
        FilterInfo filterInfo = new FilterInfo();
        FilterItemCollection filterItems = filterInfo.getFilterItems();
        filterItems.add(new FilterItemInfo("person", person.getId()));
        filterItems.add(new FilterItemInfo("effectDate", enterDate));
        SelectorItemCollection sic = new SelectorItemCollection();
        sic.add("*");
        sic.add("bill.*");
        EntityViewInfo viewInfo = EntityViewInfo.getInstance(filterInfo, sic, null);
        AdjustSalaryApplyEntryCollection adjustSalaryApplyEntryCol =
                iAdjustSalaryApplyEntry.getAdjustSalaryApplyEntryCollection(viewInfo);
        AdjustSalaryApplyEntryInfo entry = null;
        AdjustSalaryApplyInfo info = null;
        if (!adjustSalaryApplyEntryCol.isEmpty()) {
            entry = adjustSalaryApplyEntryCol.get(0);
            info = entry.getBill();
        } else {
            info = new AdjustSalaryApplyInfo();
            entry = new AdjustSalaryApplyEntryInfo();
            info.getEntry().add(entry);
            HROrgUnitInfo hrOrgUnitInfo = new HROrgUnitInfo();
            hrOrgUnitInfo.setId(BOSUuid.read("00000000-0000-0000-0000-000000000000CCE7AED4"));
            //定调薪业务组织
            info.setHrOrgUnit(hrOrgUnitInfo);
            //制单日期
            info.setApplyDate(new Date());
            //制单人
            info.setProposer(person);
            //定调薪方案
            info.setAdjustSalaryRule(calSubmitSchemeInfo);
            //单据来源(入职定薪)
            info.setBillSource(AdjBillSourceEnum.Induct_Add_Pay);
            //单据类型(专员)
            info.setBillType(AdjustBillTypeEnum.EMP_ADJ);
            entry.setPerson(person);
            entry.setHrOrgUnit(hrOrgUnitInfo);
            entry.setEffectDate(enterDate);//入职日期
        }
        //行政组织
        info.setAdminOrg(personDep);
        String salaryCalcType = dataInfo.getSalaryCalcType().getValue();
        String salaryCalcTypeSn = adjItem2CmpItem.get("ADJ028");
        if (StringUtils.isBlank(salaryCalcTypeSn)) {
            throw new BOSException("定薪项目[计薪方式代码]没匹配到对应的数据表字段");
        }
        //计薪方式
        entry.put(salaryCalcTypeSn, Integer.valueOf(salaryCalcType));
        entry.setAdminOrgUnit(personDep);
        entry.setPosition(primaryPosition);
        //定调薪档案
        entry.setAdjustEmpORelation(adjustEmpORelationInfo);
        //定调薪数据状态(未生效)
        entry.setState(EntryEffectEnum.NOT_EFFECT);
        for (int i = 0; i < entrys.size(); i++) {
            OAHireSalaryDataEntryInfo oaHireSalaryDataEntryInfo = entrys.get(i);
            AdjustSalaryItemInfo adjustSalaryItem = oaHireSalaryDataEntryInfo.getCmpItem();
            String adjustSalaryItemName = adjustSalaryItem.getName();
            String salaryItemNumber = adjustSalaryItem.getNumber();
            String fieldSn = adjItem2CmpItem.get(salaryItemNumber);
            BigDecimal money = oaHireSalaryDataEntryInfo.getMoney();
            if (StringUtils.isBlank(fieldSn)) {
                throw new BOSException("定薪项目[" + adjustSalaryItemName + "]没匹配到对应的数据表字段");
            }
            entry.put(fieldSn, money);
            entry.setCurrency(oaHireSalaryDataEntryInfo.getCurrency());
        }
        iAdjustSalaryApply.save(info);
        //提交生效
        iAdjustSalaryApply.submitEffect(info);
        dataInfo.setExecuteStatus(ExecuteStateEnum.SUCCESS);
        dataInfo.setExecuteResult("入职定薪生成成功，定调薪单据编码：" + info.getNumber());
    }

    /**
     * 获取定调薪提报方案
     *
     * @param ctx
     * @return
     * @throws BOSException
     */
    private CalSubmitSchemeInfo getCalSubmitSchemeInfo(Context ctx) throws BOSException {
        ICalSubmitScheme iCalSubmitScheme = CalSubmitSchemeFactory.getLocalInstance(ctx);
        CalSubmitSchemeCollection calSubmitSchemeCol =
                iCalSubmitScheme.getCalSubmitSchemeCollection("where number ='" + CALSUBMITSCHEMENUMBER + "'");
        if (calSubmitSchemeCol.isEmpty()) {
            throw new BOSException("编码[" + CALSUBMITSCHEMENUMBER + "]的提报方案不存在");
        }
        return calSubmitSchemeCol.get(0);
    }

    /**
     * 根据提报方案id获取定调薪项目
     *
     * @param ctx
     * @param adjustSalaryRuleId
     * @return
     * @throws BOSException
     */
    public Map<String, String> getAdjItem2CmpItem(
            Context ctx,
            String adjustSalaryRuleId
    ) throws BOSException {
        Map<String, String> mapping = new HashMap();
        if (StringUtils.isEmpty(adjustSalaryRuleId)) {
            return mapping;
        } else {
            StringBuilder sql = new StringBuilder();
            sql.append("select m.fnumber, m.fieldSn from  T_HR_SCalSubmitScheme e ");
            sql.append(" inner join  T_HR_SBatchAdjustRuleItem t on t.FCalSubmitSchemeID = e.fid ");
            sql.append(" inner join T_HR_AdjustSalaryItem m on  m.fid = t.FAdjustSalaryItemID ");
            sql.append(" where e.fid = '" + adjustSalaryRuleId + "' ");
            sql.append(" and FIsAdjustRuleShow = 1 ");
            sql.append(" and m.fcmpItemId is not null ");
            sql.append(" order by FSortCode ");
            try {
                IRowSet rs = DbUtil.executeQuery(ctx, sql.toString());
                while (rs.next()) {
                    mapping.put(rs.getString("fnumber"), "S" + rs.getString("fieldSn"));
                }
                return mapping;
            } catch (Exception e) {
                throw new BOSException(e);
            }
        }
    }
}