package com.yd.api.agms.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.yd.api.agms.service.AgmsHiringService;
import com.yd.api.agms.vo.hiring.*;
import com.yd.api.result.CommonResult;
import com.yd.api.result.CommonResultResponseVO;
import com.yd.dal.entity.agms.hiring.*;
import com.yd.dal.entity.customer.*;
import com.yd.dal.entity.customer.practitioner.PractitionerInfo;
import com.yd.dal.entity.meta.MdDropOptions;
import com.yd.dal.entity.meta.MdPractitionerHiringApproveSteps;
import com.yd.dal.entity.practitioner.hiring.HiringApproveRecords;
import com.yd.dal.entity.user.AclUser;
import com.yd.dal.mapper.customer.AclPractitionerHiringBasicInfoMapper;
import com.yd.dal.mapper.customer.AclPractitionerHiringMembershipMapper;
import com.yd.dal.mapper.customer.AclPractitionerMapper;
import com.yd.dal.service.agms.AgmsHiringDALService;
import com.yd.dal.service.customer.*;
import com.yd.dal.service.meta.MdDropOptionsDALService;
import com.yd.dal.service.meta.MdPractitionerHiringApproveStepsDALService;
import com.yd.dal.service.practitioner.PractitionerHiringDALService;
import com.yd.dal.service.user.AclUserDALService;
import com.yd.rmi.ali.send.service.SendService;
import com.yd.rmi.cache.SystemConfigService;
import com.yd.util.CommonUtil;
import com.yd.util.config.ZHBErrorConfig;
import com.yd.util.page.PageInfoUtils;
import org.apache.commons.beanutils.BeanPropertyValueEqualsPredicate;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xxy
 */
@Service("agmsHiringService")
public class AgmsHiringServiceImpl implements AgmsHiringService {
    private final static Logger logger = LoggerFactory.getLogger(AgmsHiringServiceImpl.class);

    private AgmsHiringDALService agmsHiringDalService;
    private SystemConfigService systemConfigService;
    private AclUserDALService aclUserDalService;
    private MdPractitionerHiringApproveStepsDALService mdPractitionerHiringApproveStepsDalService;
    private AclPractitionerHiringApproveRecordsDALService aclPractitionerHiringApproveRecordsDalService;
    private AclPractitionerDALService aclPractitionerDalService;
    private AclPractitionerSettingDALService aclPractitionerSettingDalService;
    private AclPractitionerHiringBasicInfoDALService aclPractitionerHiringBasicInfoDalService;
    private AclPractitionerSubordinateSystemDALService aclPractitionerSubordinateSystemDalService;
    private AclCustomerDALService aclCustomerDalService;
    @Autowired
    private AclPractitionerHiringBasicInfoMapper basicInfoMapper;
    @Autowired
    private PractitionerHiringDALService practitionerHiringDalService;
    @Autowired
    private AclPractitionerMapper aclPractitionerMapper;
    @Autowired
    private AclPractitionerHiringMembershipMapper membershipMapper;
    @Autowired
    private SendService sendService;
    @Autowired
    private AclPractitionerPotentialAssignedTrackDALService aclPractitionerPotentialAssignedTrackDALService;
    @Autowired
    private MdDropOptionsDALService mdDropOptionsDALService;

    @Autowired
    public void setAgmsHiringDalService(AgmsHiringDALService agmsHiringDalService){
        this.agmsHiringDalService = agmsHiringDalService;
    }
    @Autowired
    public void setSystemConfigService(SystemConfigService systemConfigService) {
        this.systemConfigService = systemConfigService;
    }
    @Autowired
    public void setMdPractitionerHiringApproveStepsDalService(MdPractitionerHiringApproveStepsDALService mdPractitionerHiringApproveStepsDalService) {
        this.mdPractitionerHiringApproveStepsDalService = mdPractitionerHiringApproveStepsDalService;
    }

    @Autowired
    public void setAclUserDalService(AclUserDALService aclUserDalService) {
        this.aclUserDalService = aclUserDalService;
    }

    @Autowired
    public void setAclPractitionerHiringApproveRecordsDalService(AclPractitionerHiringApproveRecordsDALService aclPractitionerHiringApproveRecordsDalService) {
        this.aclPractitionerHiringApproveRecordsDalService = aclPractitionerHiringApproveRecordsDalService;
    }

    @Autowired
    public void setAclPractitionerDalService(AclPractitionerDALService aclPractitionerDalService) {
        this.aclPractitionerDalService = aclPractitionerDalService;
    }

    @Autowired
    public void setAclPractitionerSettingDalService(AclPractitionerSettingDALService aclPractitionerSettingDalService) {
        this.aclPractitionerSettingDalService = aclPractitionerSettingDalService;
    }

    @Autowired
    public void setAclPractitionerHiringBasicInfoDalService(AclPractitionerHiringBasicInfoDALService aclPractitionerHiringBasicInfoDalService) {
        this.aclPractitionerHiringBasicInfoDalService = aclPractitionerHiringBasicInfoDalService;
    }

    @Autowired
    public void setAclPractitionerSubordinateSystemDalService(AclPractitionerSubordinateSystemDALService aclPractitionerSubordinateSystemDalService) {
        this.aclPractitionerSubordinateSystemDalService = aclPractitionerSubordinateSystemDalService;
    }

    @Autowired
    public void setAclCustomerDalService(AclCustomerDALService aclCustomerDalService) {
        this.aclCustomerDalService = aclCustomerDalService;
    }

    @Override
    public PractitionerHiringDetailResponseVO practitionerHiringDetail(PractitionerHiringDetailRequestVO requestVO) {
        PractitionerHiringDetailResponseVO responseVO = new PractitionerHiringDetailResponseVO();

        Long hiringBasicInfoId = requestVO.getHiringBasicInfoId();

        //经纪人审批基本信息
        PractitionerHiringBasicInfo practitionerHiringBasicInfo = agmsHiringDalService.findPractitionerHiringBasicInfo(hiringBasicInfoId);
        //审批经纪人关系
        PractitionerHiringMemberShip practitionerHiringMemberShip = agmsHiringDalService.findPractitionerHiringMemberShip(hiringBasicInfoId);
        //审批经纪人工作经历
        List<PractitionerHiringWorkingExperience> practitionerHiringWorkingExperienceList = agmsHiringDalService.findPractitionerHiringWorkingExperienceList(hiringBasicInfoId);
        //经纪人申请名目
        List<PractitionerHiringPersonalStatements> practitionerHiringPersonalStatementsList = agmsHiringDalService.findPractitionerHiringPersonalStatementsList(hiringBasicInfoId);
        //经纪人合同条款是否同意
        List<PractitionerHiringContractTermsConfirms> practitionerHiringContractTermsConfirmsList = agmsHiringDalService.findPractitionerHiringContractTermsConfirmsList(hiringBasicInfoId);
        //已审批结果
        List<HiringApproveRecords> hiringApproveRecordsList = practitionerHiringDalService.findHiringApproveRecordsList(hiringBasicInfoId);


        responseVO.setHiringBasicInfoId(hiringBasicInfoId);
        // 审批到哪一步
        Integer nextStepSeq = practitionerHiringDalService.getNextStepSeqByApproveStatus(practitionerHiringBasicInfo.getApproveStatus());
        responseVO.setHiringApproveStepsSeq(nextStepSeq);
        responseVO.setPractitionerHiringBasicInfo(practitionerHiringBasicInfo);
        responseVO.setPractitionerHiringMemberShip(practitionerHiringMemberShip);
        responseVO.setPractitionerHiringWorkingExperienceList(practitionerHiringWorkingExperienceList);
        responseVO.setPractitionerHiringPersonalStatementsList(practitionerHiringPersonalStatementsList);
        responseVO.setPractitionerHiringContractTermsConfirmsList(practitionerHiringContractTermsConfirmsList);
        responseVO.setPractitionerHiringApproveRecordsList(hiringApproveRecordsList);
        responseVO.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
        return responseVO;
    }

    @Override
    public PractitionerHiringListResponseVO practitionerHiringList(PractitionerHiringListRequestVO requestVO) {
        PractitionerHiringListResponseVO responseVO = new PractitionerHiringListResponseVO();
        PageInfo<PractitionerHiringListInfo> hiringListInfoPageInfo = agmsHiringDalService.practitionerHiringList(requestVO);
        responseVO.setPractitionerHiringList(hiringListInfoPageInfo);
        responseVO.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
        return responseVO;
    }

    @Override
    @Transactional
    public PractitionerHiringApproveResponseVO practitionerHiringApprove(PractitionerHiringApproveRequestVO requestVO) {
        PractitionerHiringApproveResponseVO responseVO = new PractitionerHiringApproveResponseVO();

        Integer hiringApproveStepsSeq = requestVO.getHiringApproveStepsSeq();
        Long hiringBasicInfoId = requestVO.getHiringBasicInfoId();

        AclPractitionerHiringBasicInfo basicInfo = basicInfoMapper.selectByPrimaryKey(hiringBasicInfoId);
        if (basicInfo != null && StringUtils.isNotEmpty(basicInfo.getApproveStatus()) && basicInfo.getApproveStatus().compareTo(String.valueOf(hiringApproveStepsSeq)) >= 0) {
            responseVO.setCommonResult(new CommonResult(false, "当前流程已审批，请勿重复提交"));
            return responseVO;
        }

        Integer plateform = requestVO.getPlateform();
        if (Integer.valueOf("2").equals(plateform)) {
            //通过loginId查询此登入者的经纪人id
            Long loginId = requestVO.getLoginId();
            Long practitionerId = agmsHiringDalService.findPractitionerIdByLoginId(loginId);
            AclUser user = aclUserDalService.selectByPrimaryKey(loginId);
            String mobileNo = user.getMobileNo();
            this.doApprove(practitionerId, mobileNo, user.getId(), requestVO, responseVO);
            return responseVO;

        } else {
            Long practitionerId = requestVO.getPractitionerId();
            AclPractitioner practitioner = aclPractitionerMapper.selectByPrimaryKey(practitionerId);
            String mobileNo = practitioner.getMobileNo();
            this.doApprove(practitionerId, mobileNo, Long.valueOf("-1"), requestVO, responseVO);
            return responseVO;

        }

    }

    private void doApprove(Long practitionerId, String mobileNo, Long operater,
                           PractitionerHiringApproveRequestVO requestVO, PractitionerHiringApproveResponseVO responseVO) {
        Long hiringBasicInfoId = requestVO.getHiringBasicInfoId();
        //查询审批流程
        List<MdPractitionerHiringApproveSteps> hiringApproveStepsList = systemConfigService.findHiringApproveStepsAll();
        //判断当前操作人是否具有当前流程的审批权限
        Integer currentStepSeq = requestVO.getHiringApproveStepsSeq();
        if (currentStepSeq == null) {
            responseVO.setCommonResult(new CommonResult(false, "hiringApproveStepsSeq为空，审批已结束"));
            return;
        }
        BeanPropertyValueEqualsPredicate predicate = new BeanPropertyValueEqualsPredicate("stepSeq", currentStepSeq);
        List<MdPractitionerHiringApproveSteps> steps = (List<MdPractitionerHiringApproveSteps>) CollectionUtils.select(hiringApproveStepsList, predicate);
        MdPractitionerHiringApproveSteps step = steps.get(0);

        if (StringUtils.isNotEmpty(step.getAppointedApprovePractitioners())) {
            //团队长之后的环节
            String[] appointedMobileNos = step.getAppointedApprovePractitioners().split(",");
            if (!Arrays.asList(appointedMobileNos).contains(mobileNo)) {
                responseVO.setCommonResult(new CommonResult(false, "无此流程的审批权限"));
                return;
            }
        } else {
            //辅导人或团队长
            String approveRole = step.getApproveRole();
            AclPractitionerHiringMembership membership = membershipMapper.selectByHiringBasicInfoId(hiringBasicInfoId);
            if ("subsystemOwner".equals(approveRole)) {
//                if (!practitionerId.equals(membership.getSubsystemOwnerId())) {
//                    responseVO.setCommonResult(new CommonResult(false, "无此流程的审批权限"));
//                    return;
//                }
            } else {
                if (!practitionerId.equals(membership.getMentorPractitionerId())) {
                    responseVO.setCommonResult(new CommonResult(false, "无此流程的审批权限"));
                    return;
                }
            }
        }
        // 如果是回退
        if (CommonUtil.isNullOrZero(requestVO.getApprovingStatus())) {
            Integer stepSeqStart = this.getRecordsRollBackStepSeqStart(requestVO.getStepsSeqBackTo());
            if (!Integer.valueOf("0").equals(stepSeqStart) && stepSeqStart >= step.getStepSeq()) {
                responseVO.setCommonResult(new CommonResult(false, "只能退回到已审核的步骤"));
                return;
            }
        }

        //保存审批结果
        saveRecords(practitionerId, mobileNo, hiringApproveStepsList, requestVO, responseVO);

        //保存完毕,判断是否为最后一步
        AclPractitionerHiringBasicInfo basicInfo2 = basicInfoMapper.selectByPrimaryKey(hiringBasicInfoId);
        if (String.valueOf(hiringApproveStepsList.size()).equals(basicInfo2.getApproveStatus())) {
            Long approvingStatus = requestVO.getApprovingStatus();
            String basicInfoStatus = null;
            if (approvingStatus == 1) {
                //最后一步 并同意 更新经纪人系类表
                updatePractitionerInfo(hiringBasicInfoId, operater);
                //最后一步通过发邮件通知人事填写相关经纪人信息
                this.sendMailToHR(basicInfo2);
                basicInfoStatus = "0";
                //更新增员状态为"成功报聘"
                insertPotentialAssignedTrack(basicInfo2);

            } else {
                basicInfoStatus = "-1";
            }
            // 更新basicInfo表审批状态
            AclPractitionerHiringBasicInfo updateObj = new AclPractitionerHiringBasicInfo();
            updateObj.setId(hiringBasicInfoId);
            updateObj.setApproveStatus(basicInfoStatus);
            basicInfoMapper.updateByPrimaryKeySelective(updateObj);
        }
        responseVO.setHiringBasicInfoId(hiringBasicInfoId);
        responseVO.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
    }

    private void insertPotentialAssignedTrack(AclPractitionerHiringBasicInfo basicInfo) {
        Long practitionerId = null;
        Long potentialId = basicInfo.getPractitionerPotentialId();


        AclPractitionerPotentialAssignedTrack assignedTrack = new AclPractitionerPotentialAssignedTrack();
        List<AclPractitionerPotentialAssignedTrack> assignedTrackIsLastedList = aclPractitionerPotentialAssignedTrackDALService.findByPotentialIdAndIsLasted(potentialId,1);
        //1、更新最新的状态
        if(assignedTrackIsLastedList != null && !assignedTrackIsLastedList.isEmpty()){
            List<AclPractitionerPotentialAssignedTrack> assignedTrackUpdateList = new ArrayList<>();
            for(AclPractitionerPotentialAssignedTrack item : assignedTrackIsLastedList){

                practitionerId = item.getCreatedBy();

                item.setIsLasted(0);
                item.setUpdatedBy(practitionerId);
                item.setUpdaterType(2);
                item.setUpdatedAt(new Date());
                assignedTrackUpdateList.add(item);
            }
            aclPractitionerPotentialAssignedTrackDALService.updateAll(assignedTrackUpdateList);
        }
        //2、插入
        MdDropOptions options = mdDropOptionsDALService.findById(113L);
        assignedTrack.setTrackScore(options.getDropOptionScore());
        assignedTrack.setPractitionerAssignedId(practitionerId);
        assignedTrack.setPractitionerPotentialId(potentialId);
        assignedTrack.setTrackStatusId(113L);
        assignedTrack.setTrackTime(new Date());
        assignedTrack.setIsActive(1);
        assignedTrack.setIsLasted(1);
        assignedTrack.setCreatorType(2);
        assignedTrack.setCreatedBy(practitionerId);
        assignedTrack.setCreatedAt(new Date());
        aclPractitionerPotentialAssignedTrackDALService.save(assignedTrack);

    }

    @Override
    public PractitionerHiringListResponseVO practitionerHiringListV2(PractitionerHiringListRequestVO requestVO) {
        PractitionerHiringListResponseVO resp = new PractitionerHiringListResponseVO();
        try {
            Long loginId = requestVO.getLoginId();
            String status = requestVO.getStatus();
            if (!CommonUtil.isNullOrBlank(requestVO.getName())) {
            	requestVO.setName("%"+requestVO.getName()+"%");
            }

            List<PractitionerHiringListInfo> list;
            if ("0".equals(status)) {
                list = agmsHiringDalService.queryUnhandledList(requestVO);
                // 对list分页
                PageInfo<PractitionerHiringListInfo> pageInfo = requestVO.getPageInfo();
                int pageNum = pageInfo.getPageNum();
                int pageSize = pageInfo.getPageSize();
                PageInfo<PractitionerHiringListInfo> page = PageInfoUtils.list2PageInfo(list, pageNum, pageSize);
                resp.setPractitionerHiringList(page);
            } else {
                // 通过loginId查询此登入者的经纪人id
                Long loginPractitionerId = agmsHiringDalService.findPractitionerIdByLoginId(loginId);
                PageInfo<PractitionerHiringListInfo> pageInfo = agmsHiringDalService.queryHandledList(loginPractitionerId, status, requestVO);
                resp.setPractitionerHiringList(pageInfo);
            }

            resp.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));

        } catch (Exception e) {
            e.printStackTrace();
        }
        return resp;
    }

    /**
     * AGMS -- 经纪人报聘列表查询
     * @param requestVO 请求数据
     * @return 响应数据
     */
    @Override
    public PractitionerHiringListResponseVO practitionerApplyList(PractitionerHiringListRequestVO requestVO) {
        PractitionerHiringListResponseVO resp = new PractitionerHiringListResponseVO();
        resp.setCommonResult(new CommonResult(false, ZHBErrorConfig.getErrorInfo("800001")));
        if (requestVO == null) {
            resp.setCommonResult(new CommonResult(false, "请求对象不能为空!"));
            return resp;
        }else{
            if (CommonUtil.isNullOrBlank(requestVO.getStatus())) {
                 resp.setCommonResult(new CommonResult(false, "请求信息中【审批状态】不能为空!"));
                 return resp;
            }else if (CommonUtil.isNullOrBlank(requestVO.getEndDate())) {
                resp.setCommonResult(new CommonResult(false, "请求信息中【报聘申请结束日期】不能为空!"));
                return resp;
           }
        }
        if (!CommonUtil.isNullOrBlank(requestVO.getName())) {
        	requestVO.setName("%"+requestVO.getName()+"%");
        }
        
        try {
            List<PractitionerHiringListInfo> list = agmsHiringDalService.practitionerApplyList(requestVO);
            resp.setPractitionerHiringList(PageInfoUtils.list2PageInfo(list, requestVO.getPageInfo().getPageNum(), requestVO.getPageInfo().getPageSize()));
            resp.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resp;
    }
    
    /**
     * AGMS -- 经纪人报聘列表导出
     * @param requestVO 请求数据
     * @param response 返回数据流
     * @return 响应数据
     */
    @Override
    public CommonResultResponseVO exportPractitionerApplyList(PractitionerHiringListRequestVO requestVO,HttpServletResponse response) {
    	CommonResultResponseVO resp = new CommonResultResponseVO();
        resp.setCommonResult(new CommonResult(false, ZHBErrorConfig.getErrorInfo("800001")));
        if (requestVO == null) {
            resp.setCommonResult(new CommonResult(false, "请求对象不能为空!"));
            return resp;
        }else{
            if (CommonUtil.isNullOrBlank(requestVO.getStatus())) {
                 resp.setCommonResult(new CommonResult(false, "请求信息中【审批状态】不能为空!"));
                 return resp;
            }else if (CommonUtil.isNullOrBlank(requestVO.getEndDate())) {
                resp.setCommonResult(new CommonResult(false, "请求信息中【报聘申请结束日期】不能为空!"));
                return resp;
           }
        }
        if (!CommonUtil.isNullOrBlank(requestVO.getName())) {
        	requestVO.setName("%"+requestVO.getName()+"%");
        }
        
        try {
            List<PractitionerHiringListInfo> list = agmsHiringDalService.practitionerApplyList(requestVO);
            createCSV(list, response);
            resp.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resp;
    }
    
    private void createCSV(List<PractitionerHiringListInfo> practitionerHiringListInfos, HttpServletResponse response) {
        String charset = "UTF-8"; // 读取字符编码
        String[] columnName = new String[]{"序号", "审批状态", "审批日期", "姓名", "手机号", "报聘职级", "辅导人", "介绍人", "体系", "分公司", "申请日期"};
        String tableName = "YD_Export_PractitionerArrly";
        String CSV_COLUMN_SEPARATOR = ",";//CSV文件列分隔符
        String CSV_ROW_SEPARATOR = "\r\n";//CSV文件行分隔符
        // 保证线程安全
        StringBuilder buf = new StringBuilder();
        // 组装表头
        for (String title : columnName) {
            buf.append(title).append(CSV_COLUMN_SEPARATOR);
        }
        buf.append(CSV_ROW_SEPARATOR);
        // 组装数据
        if (CollectionUtils.isNotEmpty(practitionerHiringListInfos)) {
            for (int i = 0; i < practitionerHiringListInfos.size(); i++) {
            	PractitionerHiringListInfo info = practitionerHiringListInfos.get(i);//遍历每个对象
                buf.append(i + 1).append(CSV_COLUMN_SEPARATOR);
                if("0".equals(info.getStatus())){
                    buf.append("拒绝").append(CSV_COLUMN_SEPARATOR);
                }else if("1".equals(info.getStatus())){
                    buf.append("通过").append(CSV_COLUMN_SEPARATOR);
                }else if(info.getStatus() == null){
                    buf.append("待审批").append(CSV_COLUMN_SEPARATOR);
                }else{
                    buf.append(info.getStatus()).append(CSV_COLUMN_SEPARATOR);
                }
                buf.append(info.getApprovingTime() == null ? "" : info.getApprovingTime()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getName() == null ? "" : info.getName()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getMobileNo() == null ? "" : info.getMobileNo()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getPractitionerLevel() == null ? "" : info.getPractitionerLevel()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getMentor() == null ? "" : info.getMentor()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getIntroducer() == null ? "" : info.getIntroducer()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getSubsystem() == null ? "" : info.getSubsystem()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getBranch() == null ? "" : info.getBranch()).append(CSV_COLUMN_SEPARATOR);
                buf.append(info.getApplicationTime() == null ? "" : info.getApplicationTime()).append(CSV_COLUMN_SEPARATOR);
                buf.append(CSV_ROW_SEPARATOR);
            }
        }
        // 设置文件后缀
        String fn = tableName + System.currentTimeMillis() + ".csv";
        String headStr = "attachment; filename=\"" + fn + "\"";
        // 设置响应
        response.setContentType("APPLICATION/ms-csv.numberformat");
        response.setCharacterEncoding(charset);
        response.setHeader("Content-Disposition", headStr);
        response.setHeader("Cache-Control", "max-age=30");
        response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
        response.setHeader("Pragma", "public");
        OutputStream os = null;
        try {
            os = response.getOutputStream();
            os.write(buf.toString().getBytes("GBK"));
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void saveRecords(Long loginPractitionerId,
                             String mobileNo, List<MdPractitionerHiringApproveSteps> hiringApproveStepsList,
                             PractitionerHiringApproveRequestVO requestVO,
                             PractitionerHiringApproveResponseVO responseVO) {

        Long basicInfoId = requestVO.getHiringBasicInfoId();
        String stepsSeqBackTo = requestVO.getStepsSeqBackTo();

        BeanPropertyValueEqualsPredicate predicate = new BeanPropertyValueEqualsPredicate("stepSeq", requestVO.getHiringApproveStepsSeq());
        List<MdPractitionerHiringApproveSteps> steps = (List<MdPractitionerHiringApproveSteps>) CollectionUtils.select(hiringApproveStepsList, predicate);

        if (steps.size() != 1) {
            responseVO.setHiringBasicInfoId(requestVO.getHiringBasicInfoId());
            responseVO.setCommonResult(new CommonResult(false, ZHBErrorConfig.getErrorInfo("830026")));
            return;
        }

        AclPractitionerHiringApproveRecords records = new AclPractitionerHiringApproveRecords();
        MdPractitionerHiringApproveSteps step = steps.get(0);
        records.setHiringBasicInfoId(basicInfoId);
        records.setApproveStepId(step.getId().toString());
        records.setApproveStepName(step.getStepName());
        records.setApprovingPractitionerId(loginPractitionerId);
        records.setApprovingStatus(requestVO.getApprovingStatus());
        records.setInterviewAssessment(requestVO.getInterviewAssessment());
        records.setRejectNote(requestVO.getRejectNote());
        records.setIsActive(1);
        records.setCreatedAt(new Date());
        records.setCreatedBy(loginPractitionerId);
        records.setUpdatedAt(new Date());
        records.setUpdatedBy(loginPractitionerId);
        aclPractitionerHiringApproveRecordsDalService.save(records);
        // 更新basicInfo表审批状态
        AclPractitionerHiringBasicInfo updateObj = new AclPractitionerHiringBasicInfo();
        updateObj.setId(basicInfoId);
        updateObj.setApproveStatus(step.getStepSeq().toString());
        if (CommonUtil.isNullOrZero(requestVO.getApprovingStatus())) {
            if (stepsSeqBackTo == null) {
                basicInfoMapper.changeBasicinfoUpdatable(basicInfoId);
            } else {
                updateObj.setApproveStatus(stepsSeqBackTo);
                basicInfoMapper.updateByPrimaryKeySelective(updateObj);
            }
        } else {
            basicInfoMapper.updateByPrimaryKeySelective(updateObj);
        }

        if (CommonUtil.isNullOrZero(requestVO.getApprovingStatus())) {
            // 审批回退, 将指定审批记录设置"回退"状态
            Integer stepSeqStart = this.getRecordsRollBackStepSeqStart(stepsSeqBackTo);
            this.setRecordsRollBack(stepSeqStart, step.getStepSeq(), requestVO.getRejectNote(), basicInfoId);

            responseVO.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
            return;
        }
        //判断下一个步骤是不是他
        Long id = step.getId();
        MdPractitionerHiringApproveSteps lastStep = hiringApproveStepsList.get(hiringApproveStepsList.size() - 1);
        Long lastStepId = lastStep.getId();
        //这是最后一个步骤
        if (id.equals(lastStepId)) {
            responseVO.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
            return;
        }
        //下一个步骤
        MdPractitionerHiringApproveSteps nextStep = new MdPractitionerHiringApproveSteps();
        for (int i = 0; i < hiringApproveStepsList.size(); i++) {
            MdPractitionerHiringApproveSteps stop = hiringApproveStepsList.get(i);
            Long stopId = stop.getId();
            if (id.equals(stopId)) {
                nextStep = hiringApproveStepsList.get(i + 1);
                break;
            }
        }

        //不是他
        boolean flag = this.isHasNextStep(loginPractitionerId, mobileNo, basicInfoId, nextStep);
        if (!flag) {
            if (Long.valueOf("1").equals(requestVO.getApprovingStatus())) {// 审批状态为"通过"
                // 发送短信通知及公众号推送通知下一位审批人进行审批
                agmsHiringDalService.noticeNextStep(nextStep, basicInfoId);
            }

            responseVO.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
            return;
        }
        requestVO.setHiringApproveStepsSeq(nextStep.getStepSeq());
        saveRecords(loginPractitionerId, mobileNo, hiringApproveStepsList, requestVO, responseVO);
        responseVO.setCommonResult(new CommonResult(true, ZHBErrorConfig.getErrorInfo("800000")));
    }

    private Integer getRecordsRollBackStepSeqStart(String stepsSeqBackTo) {
        Integer stepSeqStart;

        if ("-2".equals(stepsSeqBackTo)) {
            stepSeqStart = 1;
        } else if ("1".equals(stepsSeqBackTo)) {
            stepSeqStart = 2;
        } else if ("2".equals(stepsSeqBackTo)) {
            stepSeqStart = 3;
        } else if ("3".equals(stepsSeqBackTo)) {
            stepSeqStart = 4;
        } else if ("4".equals(stepsSeqBackTo)) {
            stepSeqStart = 5;
        } else {
            stepSeqStart = 0;
        }
        return stepSeqStart;
    }

    private void setRecordsRollBack(Integer stepSeqStart, Integer stepSeq, String rejectNote, Long basicInfoId) {
        rejectNote = StringUtils.isBlank(rejectNote) ? "无" : rejectNote;
        String approveName = null;

        if (Integer.valueOf("1").equals(stepSeqStart)) {
            approveName = "辅导人";
        } else if (Integer.valueOf("2").equals(stepSeqStart)) {
            approveName = "体系负责人";
        } else if (Integer.valueOf("3").equals(stepSeqStart)) {
            approveName = "公司运营主管";
        }  else if (Integer.valueOf("4").equals(stepSeqStart)) {
            approveName = "寿险总经理";
        }  else if (Integer.valueOf("5").equals(stepSeqStart)) {
            approveName = "公司总经理";
        }  else if (Integer.valueOf("0").equals(stepSeqStart)) {
            approveName = "报聘人";
        }

        // 1.获取通知人员列表
        ArrayList<Map<String, String>> list = new ArrayList<>();

        // 2.查询审批记录
        List<AclPractitionerHiringApproveRecords> recordsList = aclPractitionerHiringApproveRecordsDalService.queryListByBasicInfoId(basicInfoId);
        // 2.1 如果有审批记录，筛选需要提醒的审批经纪人id
        List<Long> practitionerIds = recordsList.stream()
                .filter(i -> (Integer.parseInt(i.getStepSeq()) >= stepSeqStart && Integer.parseInt(i.getStepSeq()) < stepSeq)
                )
                .map(AclPractitionerHiringApproveRecords::getApprovingPractitionerId)
                .collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(practitionerIds)) {
            List<PractitionerInfo> practitionerList = aclPractitionerDalService.findPractitionerInfoByIdList(practitionerIds);
            for (PractitionerInfo practitionerInfo : practitionerList) {
                Map<String, String> map = new HashMap<>();
                map.put("name", practitionerInfo.getName());
                map.put("mobileNo", practitionerInfo.getMobileNo());
                map.put("ydWechatOpenid", practitionerInfo.getYdWechatOpenid());

                list.add(map);
            }
        }
        // 2.2 如果退回到报聘人，还要提醒报聘人
        if (Integer.valueOf("0").equals(stepSeqStart)) {
            AclPractitionerHiringBasicInfo basicInfo = aclPractitionerHiringBasicInfoDalService.findById(basicInfoId);
            AclCustomer customer = aclCustomerDalService.findByMobileNo(basicInfo.getMobileNo());
            Map<String, String> map = new HashMap<>();
            map.put("name", basicInfo.getName());
            map.put("mobileNo", basicInfo.getMobileNo());
            map.put("ydWechatOpenid", customer == null ? null : customer.getYdWechatOpenid());

            list.add(map);
        }
        // 3.回退提醒发消息(短信和微信推送)
        if (CollectionUtils.isNotEmpty(list)) {
            this.approveRollBackNoticeSendMsg(approveName, rejectNote, list, basicInfoId);
        }
    }

    private void approveRollBackNoticeSendMsg(String approveName, String rejectNote, List<Map<String, String>> practitionerList, Long basicInfoId) {
        AclPractitionerHiringBasicInfo basicInfo = aclPractitionerHiringBasicInfoDalService.findById(basicInfoId);
        // 查询辅导人所在S1,S2,S3
        AclPractitionerHiringMembership hiringMemberShip = practitionerHiringDalService.queryHiringMemberShip(basicInfoId);
        // 报聘人组织关系
        String orgInfo = practitionerHiringDalService.getHiringOrganizationInfo(basicInfo, hiringMemberShip);

        // 短信模板
        String templateCode = systemConfigService.getSingleConfigValue("ALI_SMS_HiringApproveRollBackNotice");
        String jumpUrl = systemConfigService.getSingleConfigValue("hiringApprove_page_url");
        // 被提醒人的姓名手机号
        String mobileNo;
        String name;
        for (Map<String, String> practitioner : practitionerList) {
            mobileNo = practitioner.get("mobileNo");
            name = practitioner.get("name");
            // 1.发短信
            if (StringUtils.isNotBlank(mobileNo)) {
                logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》电子报聘退回发送短信");
                logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》" + name + ": " + mobileNo);
                // 短信内容 ${name}，您好！${hiringName}报聘审批被退回至${approveName}
                JSONObject content = new JSONObject();
                content.put("name", name);
                content.put("hiringName", orgInfo);
                if (mobileNo.equals(basicInfo.getMobileNo())) {
                    content.put("approveName", "公众号，退回原因<" + rejectNote + ">");
                } else {
                    content.put("approveName", approveName + "，退回原因<" + rejectNote + ">" + "，请至“赢家平台>我的团队-报聘审批”进行查看审批，谢谢！" + jumpUrl);
                }
                sendService.sendEmailOrSMS("sms", mobileNo, "0", content.toJSONString(), templateCode, null, null, "电子报聘审批退回", 99, basicInfoId);
            } else {
                logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》电子报聘聘退回发送短信电话号码不存在");
                logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》" + name + ": " + mobileNo);
            }
            // 2.微信公众号推送

        }
        // 微信模板
        String firstValue = "name，您好！hiringName经纪人报聘审批被退回";

        firstValue = firstValue.replace("hiringName", orgInfo);
        StringBuffer stringBuffer = new StringBuffer(firstValue);
        stringBuffer.append("；审批退回，退回原因<").append(rejectNote).append(">");

        // 用现有方法发微信
        agmsHiringDalService.noticeSendWeChatMsg(stringBuffer.toString(), "退回待审批", practitionerList, basicInfo);
    }

    private boolean isHasNextStep(Long loginPractitionerId, String mobileNo, Long basicInfoId, MdPractitionerHiringApproveSteps nextStep) {
        // 判断是辅导人和团队长
        if (!CommonUtil.isNullOrZero(loginPractitionerId)) {
            String approveRole = nextStep.getApproveRole();
            if (StringUtils.isNotEmpty(approveRole)) {
                AclPractitionerHiringMembership membership = membershipMapper.selectByHiringBasicInfoId(basicInfoId);
                if (membership != null) {
                    if (loginPractitionerId.equals(membership.getApprovedBy())) {
                        return true;
                    }
                }
            }
        }
        // 判断是否是AGMS中审批的人员
        String appointedApprovePractitioners = nextStep.getAppointedApprovePractitioners();
        if (StringUtils.isNotEmpty(appointedApprovePractitioners)) {
            List<String> hiringApproveMobileNos = new ArrayList<>(Arrays.asList(appointedApprovePractitioners.split(",")));
            if (hiringApproveMobileNos.contains(mobileNo)) {
                return true;
            }
        }
        return false;
    }

    private void updatePractitionerInfo(Long hiringBasicInfoId,Long operater) {
        //更新经纪人系类表
        //ag_acl_practitioner
        //ag_acl_practitioner_setting
        //ag_acl_practitioner_subordinate_system(如果是团队长)operator
        AclPractitionerHiringBasicInfo basicInfo = aclPractitionerHiringBasicInfoDalService.findById(hiringBasicInfoId);
        AclPractitionerHiringMembership membership = agmsHiringDalService.queryHiringMemberShip(hiringBasicInfoId);
        AclPractitionerSubordinateSystem subordinateSystem = aclPractitionerSubordinateSystemDalService.findById(membership.getSubsystemId());
        AclCustomer customer = aclCustomerDalService.findByMobileNo(basicInfo.getMobileNo());
        AclPractitioner practitioner = new AclPractitioner();
        practitioner.setInsurerId(888L);
        practitioner.setInsurerBranchId(membership.getBranchId());
        practitioner.setDeptId(subordinateSystem != null ? subordinateSystem.getDeptId() : null);
        practitioner.setSubordinateSystemId(membership.getSubsystemId());
        practitioner.setPractitionerCode(" ");
        practitioner.setName(basicInfo.getName());
        practitioner.setMobileNo(basicInfo.getMobileNo());
        practitioner.setIdTypeId(basicInfo.getIdTypeId());
        practitioner.setIdType(basicInfo.getIdType());
        practitioner.setIdNo(basicInfo.getIdNo());

        practitioner.setS1Id(membership.getS1Id());
        practitioner.setS2Id(membership.getS2Id());
        practitioner.setS3Id(membership.getS3Id());

        Date practitionerBirthdate = CommonUtil.stringParseDate(basicInfo.getPractitionerBirthdate(), "yyyy-MM-dd");
        practitioner.setPractitionerBirthdate(practitionerBirthdate);
        practitioner.setPractitionerRegNo(" ");
        practitioner.setPractitionerRegCompany(" ");
        practitioner.setCustomerId(customer != null ? customer.getId() : null);
        practitioner.setIsActive(1);
        practitioner.setCreatedAt(new Date());
        practitioner.setCreatedBy(operater);
        practitioner.setUpdatedAt(new Date());
        practitioner.setUpdatedBy(operater);
        practitioner.setProvinceId(basicInfo.getProvinceId());
        practitioner.setProvinceName(basicInfo.getProvinceName());
        practitioner.setCityId(basicInfo.getCityId());
        practitioner.setCityName(basicInfo.getCityName());
        if (StringUtils.isNotBlank(basicInfo.getResidentAddress())) {
            practitioner.setDetailAddress(basicInfo.getResidentAddress());
        } else {
            practitioner.setDetailAddress(basicInfo.getProvinceName() + basicInfo.getCityName());
        }
        practitioner.setWechatId(basicInfo.getWechatId());
        practitioner.setIsProfileShow(0);
        practitioner.setIsNameShow(0);
        practitioner.setIsMobileShow(0);
        practitioner.setEducationLevel(basicInfo.getLastGraduateCode());
        practitioner.setGraduatedUniversity(basicInfo.getLastGraduateSchool());
        practitioner.setMentorId(membership.getMentorPractitionerId());
        if(practitioner.getMentorId() != null){
        	AclPractitioner aclPractitionerMentor = aclPractitionerDalService.findById(practitioner.getMentorId());
        	if(aclPractitionerMentor != null && aclPractitionerMentor.getMentorId() != null){
        		practitioner.setInMentorId(aclPractitionerMentor.getMentorId());
        	}
        }
        
        practitioner.setIntroducerId(membership.getIntroducerPractitionerId());
        practitioner.setGender(basicInfo.getGender());
        practitioner.setHiringBasicInfoId(hiringBasicInfoId);
        //0000945: 经纪人维护页面添加字段，当经纪人电子报聘通过审核后，系统自动同步报聘信息
        practitioner.setAccountBank(basicInfo.getBankAccountOpening());
        practitioner.setBankCardNo(basicInfo.getBankAccountId());
        practitioner.setEmail(basicInfo.getEmail());
        aclPractitionerDalService.save(practitioner);

        AclPractitionerSetting setting = new AclPractitionerSetting();
        setting.setPractitionerId(practitioner.getId());
        setting.setPractitionerTypeId(28L);
        setting.setPractitionerLevel(membership.getMdDropOptionId());
        setting.setIsActive(1);
        setting.setCreatedAt(new Date());
        setting.setCreatedBy(operater);
        setting.setUpdatedAt(new Date());
        setting.setUpdatedBy(operater);
        aclPractitionerSettingDalService.save(setting);
    }

    private PractitionerHiringApproveSteps getHiringApproveStatus(Long loginId, String practitionerLevelId, List<PractitionerHiringApproveRecords> practitionerHiringApproveRecordsList) {
        //是否可进行审批操作 0.不可审批(未到)  1.可审批  2.已审批  3.无权审批(默认) 4.已驳回
        Long hiringApproveStatus = 3L;
        //审批到哪一步了
        Long hiringApproveStepsSeq = null;
        //查看审批流程最后一次,是否通过
        PractitionerHiringApproveRecords recordsFinally = new PractitionerHiringApproveRecords();
        if (!practitionerHiringApproveRecordsList.isEmpty()) {
            recordsFinally = practitionerHiringApproveRecordsList.get(practitionerHiringApproveRecordsList.size() - 1);
            Long approvingStatusId = recordsFinally.getApprovingStatusId();
            if (CommonUtil.isNullOrZero(approvingStatusId)) {
                //已驳回
                hiringApproveStatus = 4L;
                return new PractitionerHiringApproveSteps(hiringApproveStatus, hiringApproveStepsSeq);
            }
        }

        //通过loginId查询对应的经纪人id
        Long loginPractitionerId = agmsHiringDalService.findPractitionerIdByLoginId(loginId);
        //AGMS登入者手机号不是经纪人手机号,无权审批
        if (!CommonUtil.isNullOrZero(loginPractitionerId)) {
            return new PractitionerHiringApproveSteps(hiringApproveStatus, hiringApproveStepsSeq);
        }
        //遍历已审批结果,查看此agms登入者是否已审批
        for (PractitionerHiringApproveRecords practitionerHiringApproveRecords : practitionerHiringApproveRecordsList) {
            Long approvingPractitionerId = practitionerHiringApproveRecords.getApprovingPractitionerId();
            if (approvingPractitionerId.equals(loginPractitionerId)) {
                //已审批
                hiringApproveStatus = 2L;
                return new PractitionerHiringApproveSteps(hiringApproveStatus, hiringApproveStepsSeq);
            }
        }
        //查询审批流程
        List<MdPractitionerHiringApproveSteps> hiringApproveSteps = systemConfigService.findHiringApproveStepsByPractitionerLevel(practitionerLevelId);
        //通过loginId查询登入者手机号码
        AclUser user = aclUserDalService.selectByPrimaryKey(loginId);
        String loginMobileNo = user.getMobileNo();
        //所有通过agms审批的手机号码
        List<String> hiringApproveMobileNo = systemConfigService.findHiringApproveMobileNo(hiringApproveSteps, practitionerLevelId);
        //agms登入者无审批权力
        if (!hiringApproveMobileNo.contains(loginMobileNo)) {
            return new PractitionerHiringApproveSteps(hiringApproveStatus, hiringApproveStepsSeq);
        }
        //此经纪人最后一次审批步骤id
        hiringApproveStepsSeq = recordsFinally.getApproveStepId();
        //查询此经纪人最后一次审批步骤详细信息
        Long stepId = 0L;
        for (int i = 0; i < hiringApproveSteps.size(); i++) {
            Long id = hiringApproveSteps.get(i).getId();
            if (id.equals(hiringApproveStepsSeq)) {
                stepId = id;
                break;
            }
        }
        MdPractitionerHiringApproveSteps mdPractitionerHiringApproveSteps = hiringApproveSteps.get(Integer.parseInt(stepId.toString()));
        //通过手机号码查询此agmd登入者拥有哪些审批步骤(肯定有值)
        List<MdPractitionerHiringApproveSteps> hiringApproves = mdPractitionerHiringApproveStepsDalService.findByAppointedApprovePractitioners(loginMobileNo);
        //最后一个审批步骤的seq
        Integer stepSeq = mdPractitionerHiringApproveSteps.getStepSeq() == null ? 0 : mdPractitionerHiringApproveSteps.getStepSeq();
        MdPractitionerHiringApproveSteps loginHiringApproveStep = null;
        for (MdPractitionerHiringApproveSteps hiringApprove : hiringApproves) {
            Integer loginStepSeq = hiringApprove.getStepSeq();
            if (stepSeq < loginStepSeq) {
                loginHiringApproveStep = hiringApprove;
                break;
            }
        }
        if (loginHiringApproveStep == null){
            hiringApproveStatus = 2L;
            return new PractitionerHiringApproveSteps(hiringApproveStatus, hiringApproveStepsSeq);
        }
        //查看下一审批步骤
        mdPractitionerHiringApproveSteps = hiringApproveSteps.get(Integer.parseInt(stepId.toString())+1);
        Long mdPractitionerHiringApproveStepsSeq = Long.valueOf(mdPractitionerHiringApproveSteps.getStepSeq());
        Long loginHiringApproveStepId = loginHiringApproveStep.getId();
        if (mdPractitionerHiringApproveStepsSeq.equals(loginHiringApproveStepId)){
            //可审批
            hiringApproveStatus = 1L;
            hiringApproveStepsSeq = mdPractitionerHiringApproveStepsSeq;
        }else {
            //0.不可审批(未到)
            hiringApproveStatus = 0L;
        }
        return new PractitionerHiringApproveSteps(hiringApproveStatus, hiringApproveStepsSeq);
    }

    /**
     * 报聘审核通过，通知人事
     * @param basicInfo
     */
    private void sendMailToHR(AclPractitionerHiringBasicInfo basicInfo) {
        //收件地址
        String address = systemConfigService.getSingleConfigValue("PractitionerHiringNotifyAddress");
        //抄送地址
        List<String> ccList = systemConfigService.getListConfigValue("PractitionerHiringNotifyCCAddress");
        List<String> arrList = new ArrayList(ccList);
        String[] ccAddresses = arrList.toArray(new String[arrList.size()]);

        AclPractitionerHiringMembership memberShip = membershipMapper.selectByHiringBasicInfoId(basicInfo.getId());

        StringBuilder messageText = new StringBuilder();
        messageText.append("银盾人事你好，");
        if (Long.valueOf("30").equals(memberShip.getMdDropOptionId())) {
            // XX 分公司的 XXX
            messageText.append(memberShip.getBranch()).append("的").append(basicInfo.getName());
        } else {
            // XX 分公司 XX 体系下的 XXX
            messageText.append(memberShip.getBranch()).append(memberShip.getSubsystem()).append("体系下的").append(basicInfo.getName());
        }
        messageText.append("的电子报聘流程线上审批已经通过，请尽快帮助完成该报聘人的经纪人执业登记，并在AGMS 里更新并生成电子合同。谢谢！");

        String subject = "电子报聘审批通过";
        sendService.sendEmailOrSMS("email", address, "3", messageText.toString(), null, subject, ccAddresses, "电子报聘审批通过", 99, null);
    }
}
