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

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yd.api.agms.vo.hiring.PractitionerHiringListRequestVO;
import com.yd.dal.entity.agms.hiring.*;
import com.yd.dal.entity.customer.AclPractitioner;
import com.yd.dal.entity.customer.AclPractitionerHiringBasicInfo;
import com.yd.dal.entity.customer.AclPractitionerHiringMembership;
import com.yd.dal.entity.customer.AclPractitionerSubordinateSystem;
import com.yd.dal.entity.customer.practitioner.PractitionerInfo;
import com.yd.dal.entity.customer.practitioner.PractitionerSubordinateInfo;
import com.yd.dal.entity.meta.MdPractitionerHiringApproveSteps;
import com.yd.dal.entity.user.AclUser;
import com.yd.dal.mapper.agms.AgmsHiringMapper;
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.AclPractitionerDALService;
import com.yd.dal.service.customer.AclPractitionerHiringBasicInfoDALService;
import com.yd.dal.service.customer.AclPractitionerSubordinateSystemDALService;
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.rmi.tencent.wechat.service.WechatService;
import com.yd.rmi.tencent.wechatinterf.pojo.templetemessage.DataDetailInfo;
import com.yd.rmi.tencent.wechatinterf.pojo.templetemessage.SendTemplateRequest;
import com.yd.rmi.tencent.wechatinterf.pojo.templetemessage.TemplateDataInfo;
import com.yd.util.CommonUtil;
import com.yd.util.page.PageInfoUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author xxy
 */
@Service("agmsHiringDALService")
public class AgmsHiringDALServiceImpl implements AgmsHiringDALService {
    private final static Logger logger = LoggerFactory.getLogger(AgmsHiringDALServiceImpl.class);

    private AgmsHiringMapper agmsHiringMapper;
    @Autowired
    private AclUserDALService aclUserDalService;
    @Autowired
    private MdPractitionerHiringApproveStepsDALService mdPractitionerHiringApproveStepsDalService;
    @Autowired
    private PractitionerHiringDALService practitionerHiringDalService;
    @Autowired
    private AclPractitionerSubordinateSystemDALService aclPractitionerSubordinateSystemDalService;
    @Autowired
    private AclPractitionerHiringMembershipMapper membershipMapper;
    @Autowired
    private AclPractitionerDALService aclPractitionerDALService;
    @Autowired
    private AclPractitionerHiringBasicInfoDALService aclPractitionerHiringBasicInfoDalService;
    @Autowired
    private AclPractitionerMapper aclPractitionerMapper;
    @Autowired
    private SystemConfigService systemConfigService;
    @Autowired
    private WechatService wechatService;
    @Autowired
    private SendService sendService;

    @Autowired
    public void setAgmsHiringMapper(AgmsHiringMapper agmsHiringMapper){
        this.agmsHiringMapper = agmsHiringMapper;
    }

    @Override
    public PractitionerHiringBasicInfo findPractitionerHiringBasicInfo(Long hiringBasicInfoId) {
        return agmsHiringMapper.findPractitionerHiringBasicInfo(hiringBasicInfoId);
    }

    @Override
    public PractitionerHiringMemberShip findPractitionerHiringMemberShip(Long hiringBasicInfoId) {
        PractitionerHiringMemberShip practitionerHiringMemberShip = agmsHiringMapper.findPractitionerHiringMemberShip(hiringBasicInfoId);
        AclPractitionerHiringMembership hiringMemberShip = this.queryHiringMemberShip(hiringBasicInfoId);

        practitionerHiringMemberShip.setS1TeamLeaderId(hiringMemberShip.getS1TeamLeaderId());
        practitionerHiringMemberShip.setS2TeamLeaderId(hiringMemberShip.getS2TeamLeaderId());
        practitionerHiringMemberShip.setS3TeamLeaderId(hiringMemberShip.getS3TeamLeaderId());

        practitionerHiringMemberShip.setS1TeamLeaderName(hiringMemberShip.getS1TeamLeaderName());
        practitionerHiringMemberShip.setS2TeamLeaderName(hiringMemberShip.getS2TeamLeaderName());
        practitionerHiringMemberShip.setS3TeamLeaderName(hiringMemberShip.getS3TeamLeaderName());

        practitionerHiringMemberShip.setS1SubordinateSystemName(hiringMemberShip.getS1SubordinateSystemName());
        practitionerHiringMemberShip.setS2SubordinateSystemName(hiringMemberShip.getS2SubordinateSystemName());
        practitionerHiringMemberShip.setS3SubordinateSystemName(hiringMemberShip.getS3SubordinateSystemName());

        return practitionerHiringMemberShip;
    }

    @Override
    public AclPractitionerHiringMembership queryHiringMemberShip(Long hiringBasicInfoId) {
        AclPractitionerHiringMembership hiringMemberShip = membershipMapper.selectByHiringBasicInfoId(hiringBasicInfoId);
        if (hiringMemberShip.getMentorPractitionerId() == null) {
            return hiringMemberShip;
        }
        AclPractitioner mentor = aclPractitionerDALService.findPractitionerById(hiringMemberShip.getMentorPractitionerId());
        hiringMemberShip.setS1Id(mentor.getS1Id());
        hiringMemberShip.setS2Id(mentor.getS2Id());
        hiringMemberShip.setS3Id(mentor.getS3Id());

        // 查询并显示“辅导人”所属的S1分部，分部负责人，S2体系，体系负责人，S3纵队，纵队负责人，没有的显示空
        List<AclPractitionerSubordinateSystem> subordinateSystemList = aclPractitionerSubordinateSystemDalService.findAll();
        Map<Long, AclPractitionerSubordinateSystem> subordinateSystemMap = new HashMap<>();
        subordinateSystemList.forEach(i -> subordinateSystemMap.put(i.getId(), i));

        Map<Long, AclPractitioner> aclPractitionerMap = aclPractitionerDALService.findAllMap();
        //所属体系
        AclPractitionerSubordinateSystem subordinateSystem = null;
        //体系团队长
        AclPractitioner systemOwner = null;

        if (mentor.getS1Id() != null) {
            subordinateSystem = subordinateSystemMap.get(mentor.getS1Id());
            if (subordinateSystem != null) {
                hiringMemberShip.setS1SubordinateSystemName(subordinateSystem.getName());

                systemOwner = aclPractitionerMap.get(subordinateSystem.getOwnerPractitionerId());
                hiringMemberShip.setS1TeamLeaderName(systemOwner != null ? systemOwner.getName() : null);
                hiringMemberShip.setS1TeamLeaderId(systemOwner != null ? systemOwner.getId() : null);
            }
        }

        if (null != mentor.getS2Id()) {
            subordinateSystem = subordinateSystemMap.get(mentor.getS2Id());
            if (subordinateSystem != null) {
                hiringMemberShip.setS2SubordinateSystemName(subordinateSystem != null ? subordinateSystem.getName() : null);

                systemOwner = aclPractitionerMap.get(subordinateSystem.getOwnerPractitionerId());
                hiringMemberShip.setS2TeamLeaderName(systemOwner != null ? systemOwner.getName() : null);
                hiringMemberShip.setS2TeamLeaderId(systemOwner != null ? systemOwner.getId() : null);
            }
        }
        if (null != mentor.getS3Id()) {
            subordinateSystem = subordinateSystemMap.get(mentor.getS3Id());
            if (subordinateSystem != null) {
                hiringMemberShip.setS3SubordinateSystemName(subordinateSystem != null ? subordinateSystem.getName() : null);

                systemOwner = aclPractitionerMap.get(subordinateSystem.getOwnerPractitionerId());
                hiringMemberShip.setS3TeamLeaderName(systemOwner != null ? systemOwner.getName() : null);
                hiringMemberShip.setS3TeamLeaderId(systemOwner != null ? systemOwner.getId() : null);
            }
        }

        return hiringMemberShip;
    }

    @Override
    public void noticeNextStep(MdPractitionerHiringApproveSteps nextStep, Long basicInfoId) {
        AclPractitionerHiringBasicInfo basicInfo = aclPractitionerHiringBasicInfoDalService.findById(basicInfoId);
        // 查询辅导人所在S1,S2,S3
        AclPractitionerHiringMembership hiringMemberShip = practitionerHiringDalService.queryHiringMemberShip(basicInfoId);

        // 1.获取下一步审批人的手机号
        String[] mobileNoArray = new String [1];
        // 1.1 如果是体系负责人
        if ("mentor".equals(nextStep.getApproveRole())) {
            AclPractitioner aclPractitioner = aclPractitionerMapper.selectByPrimaryKey(hiringMemberShip.getMentorPractitionerId());
            mobileNoArray[0] = aclPractitioner.getMobileNo();
        } else if ("subsystemOwner".equals(nextStep.getApproveRole())) {
            AclPractitioner aclPractitioner = aclPractitionerMapper.selectByPrimaryKey(hiringMemberShip.getApprovedBy());
            mobileNoArray[0] = aclPractitioner.getMobileNo();
        } else {
            // 1.2 团队长之后的环节, 可能会有多个审批人
            mobileNoArray = nextStep.getAppointedApprovePractitioners().split(",");
        }
        // 1.3 查询审批人列表
        List<PractitionerInfo> practitionerList = aclPractitionerDALService.findPractitionerInfoByMobileList(Arrays.asList(mobileNoArray));
        // 2.获取报聘人组织架构信息
        String orgInfo = practitionerHiringDalService.getHiringOrganizationInfo(basicInfo, hiringMemberShip);

        // 发送短信通知下一位审批人进行审批
        this.noticeSendSMS(orgInfo, practitionerList, basicInfo);
        // 公众号推送通知下一位审批人进行审批
        String firstValue = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TEMPLATE_FIRST_HIRING");
        firstValue = firstValue.replace("hiringName", orgInfo);

        ArrayList<Map<String, String>> list = new ArrayList<>();
        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);
        }

        this.noticeSendWeChatMsg(firstValue, "待审批", list, basicInfo);
    }

    @Override
    public void noticeSendWeChatMsg(String firstValue, String noticeMsg, List<Map<String, String>> practitionerList, AclPractitionerHiringBasicInfo basicInfo) {
        // 读取数据库配置
        String templateId = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TEMPLATE_ID_HIRING");
        String jumpUrl = systemConfigService.getSingleConfigValue("hiringApprove_page_url");

//        String firstValue = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TEMPLATE_FIRST_HIRING");
        String remarkValue = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TEMPLATE_REMARK_HIRING");
        String color = systemConfigService.getSingleConfigValue("TENCENT_WECHAT_TEMPLATE_COLOR_XB");

        // 组装模板数据
        TemplateDataInfo dataInfo = new TemplateDataInfo();
        DataDetailInfo first = new DataDetailInfo();
        DataDetailInfo keyword1 = new DataDetailInfo(noticeMsg, color);
        DataDetailInfo keyword2 = new DataDetailInfo(CommonUtil.dateParseString(basicInfo.getCreatedAt(),"yyyy-MM-dd HH:mm:ss"), null);
        DataDetailInfo remark = new DataDetailInfo(remarkValue, null);

        dataInfo.setFirst(first);
        dataInfo.setKeyword1(keyword1);
        dataInfo.setKeyword2(keyword2);
        dataInfo.setRemark(remark);

        // 调微信接口
        if (StringUtils.isNotBlank(templateId)) {
            SendTemplateRequest sendTemplateRequest = new SendTemplateRequest();
            sendTemplateRequest.setTemplateId(templateId);
            sendTemplateRequest.setData(dataInfo);
            sendTemplateRequest.setUrl(jumpUrl);

            for (Map<String, String> practitionerInfo : practitionerList) {
                // openId不为null, 执行
                if (StringUtils.isNotBlank(practitionerInfo.get("ydWechatOpenid"))) {
                    sendTemplateRequest.setToUser(practitionerInfo.get("ydWechatOpenid"));
                    // 审批人姓名
                    first.setValue(firstValue.replace("name", practitionerInfo.get("name")));

                    logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》发送微信模板消息审批人");
                    logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》" + practitionerInfo.get("name"));
                    // 微信通知
                    wechatService.sendTemplateMessage(sendTemplateRequest);
                } else {
                    logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》发送微信模板消息审批人openId为空");
                    logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》" + practitionerInfo.get("name"));
                }
            }
        }
    }

    private void noticeSendSMS(String hiringName, List<PractitionerInfo> practitionerList, AclPractitionerHiringBasicInfo basicInfo) {
        // 审批人姓名, 手机号
        String name;
        String mobileNo;
        for (PractitionerInfo practitionerInfo : practitionerList) {
            name = practitionerInfo.getName();
            mobileNo = practitionerInfo.getMobileNo();
            if (StringUtils.isNotBlank(mobileNo)) {
                logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》电子报聘发送短信");
                logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》" + name + ": " + mobileNo);
                // 发短信
                // ${name}，您好！${name2}(S3纵队S2体系S1分部的XX)经纪人已提交报聘审批，请至“赢家平台>我的团队-报聘审批”进行查看审批，谢谢！
                String templateCode = systemConfigService.getSingleConfigValue("ALI_SMS_HiringApproveNotice");
                String content = "{\"name\":\"" + name + "\",\"hiringName\":\"" + hiringName + "\"}";
                sendService.sendEmailOrSMS("sms", mobileNo, "0", content, templateCode, null, null, "电子报聘审批通知", 99, basicInfo.getId(), null);
            } else {
                logger.error("【》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》电子报聘审批人电话号码不存在");
                throw new RuntimeException("电子报聘审批人电话号码不存在");
            }

        }
    }

    @Override
    public List<PractitionerHiringWorkingExperience> findPractitionerHiringWorkingExperienceList(Long hiringBasicInfoId) {
        return agmsHiringMapper.findPractitionerHiringWorkingExperienceList(hiringBasicInfoId);
    }

    @Override
    public List<PractitionerHiringPersonalStatements> findPractitionerHiringPersonalStatementsList(Long hiringBasicInfoId) {
        return agmsHiringMapper.findPractitionerHiringPersonalStatementsList(hiringBasicInfoId);
    }

    @Override
    public List<PractitionerHiringContractTermsConfirms> findPractitionerHiringContractTermsConfirmsList(Long hiringBasicInfoId) {
        return agmsHiringMapper.findPractitionerHiringContractTermsConfirmsList(hiringBasicInfoId);
    }

    @Override
    public List<PractitionerHiringApproveRecords> findPractitionerHiringApproveRecordsList(Long hiringBasicInfoId) {
        return agmsHiringMapper.findPractitionerHiringApproveRecordsList(hiringBasicInfoId);
    }

    @Override
    public Long findPractitionerIdByLoginId(Long loginId) {
        return agmsHiringMapper.findPractitionerIdByLoginId(loginId);
    }

    @Override
    public PageInfo<PractitionerHiringListInfo> practitionerHiringList(PractitionerHiringListRequestVO requestVO) {
        String orderBy = "hiringBasicInfoId desc";
        PageInfo<PractitionerHiringListInfo> pageInfo = requestVO.getPageInfo();
        PageHelper.startPage(pageInfo.getPageNum(),pageInfo.getPageSize(),orderBy);
        Page<PractitionerHiringListInfo> destList = agmsHiringMapper.practitionerHiringList(requestVO);
        pageInfo = new PageInfo<>(destList);
        return pageInfo;
    }

    @Override
    public PageInfo<PractitionerHiringListInfo> queryHandledList(Long loginPractitionerId, String status, PractitionerHiringListRequestVO requestVO) {
        //体系查询调整，如果体系为S3，则需要查询它下面的所有子集
        PractitionerSubordinateInfo practitionerSubordinateInfo = new PractitionerSubordinateInfo();
        BeanUtils.copyProperties(requestVO,practitionerSubordinateInfo);
        practitionerSubordinateInfo.setInsurerBranchId(requestVO.getBranchId());
        List<Long> subsystemIdList = aclPractitionerSubordinateSystemDalService.getLongs(practitionerSubordinateInfo);

        List<PractitionerHiringListInfo> destList =
                agmsHiringMapper.queryHandledList(loginPractitionerId, status, requestVO.getBranchId(),
                        requestVO.getDeptId(),
                        subsystemIdList,
                        requestVO.getName());

        // list去重
        List<PractitionerHiringListInfo> uniqueList = destList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(
                // 利用 TreeSet 的排序去重构造函数来达到去重元素的目的
                // 根据hiringBasicInfoId去重
                () -> new TreeSet<>(Comparator.comparingLong(PractitionerHiringListInfo::getHiringBasicInfoId))), ArrayList::new));

        // 去重后的list分页
        PageInfo<PractitionerHiringListInfo> pageInfo = requestVO.getPageInfo();
        int pageNum = pageInfo.getPageNum();
        int pageSize = pageInfo.getPageSize();
        PageInfo<PractitionerHiringListInfo> page = PageInfoUtils.list2PageInfo(uniqueList, pageNum, pageSize);

        return page;
    }

    @Override
    public List<PractitionerHiringListInfo> queryUnhandledList(PractitionerHiringListRequestVO requestVO) {
        // 结果集
        List<PractitionerHiringListInfo> dataList = new ArrayList<>();

        AclUser user = aclUserDalService.selectByPrimaryKey(requestVO.getLoginId());
        String loginMobileNo = user.getMobileNo();
        // 查询该号码具有的审批步骤
        List<MdPractitionerHiringApproveSteps> ownSteps = mdPractitionerHiringApproveStepsDalService.findByAppointedApprovePractitioners(loginMobileNo);
        if (CollectionUtils.isEmpty(ownSteps)) {
            return dataList;
        }

        // 根据当前用户拥有的审批步骤查询每一步能够审批的数据
        String stepName;
        Integer stepSeq;
        String canAprroveGrade;

        //体系查询调整，如果体系为S3，则需要查询它下面的所有子集
        PractitionerSubordinateInfo practitionerSubordinateInfo = new PractitionerSubordinateInfo();
        BeanUtils.copyProperties(requestVO,practitionerSubordinateInfo);
        practitionerSubordinateInfo.setInsurerBranchId(requestVO.getBranchId());
        List<Long> subsystemIdList = aclPractitionerSubordinateSystemDalService.getLongs(practitionerSubordinateInfo);

        for (MdPractitionerHiringApproveSteps step : ownSteps) {
            stepName = step.getStepName();
            stepSeq = step.getStepSeq();
            canAprroveGrade = step.getCanAprroveGrade();

            List<String> canAprroveGrades = new ArrayList<>();
            canAprroveGrades.addAll(Arrays.asList(canAprroveGrade.split(",")));

            String approveStatus = practitionerHiringDalService.getApproveStatusByStepSeq(stepSeq);
            List<PractitionerHiringListInfo> resultList =
                    agmsHiringMapper.queryUnhandledList(approveStatus, canAprroveGrades,
                            requestVO.getBranchId(),
                            requestVO.getDeptId(),
                            subsystemIdList,
                            requestVO.getName()
                    );
            if (CollectionUtils.isNotEmpty(resultList)) {
                dataList.addAll(resultList);
            }

            if (canAprroveGrades.contains("30")) {
                List<PractitionerHiringListInfo> s2List = agmsHiringMapper.queryS2List(approveStatus,requestVO.getName());
                dataList.addAll(s2List);
            }

        }
        // 每个审核步骤可能查询出重复数据， 需去重
        List<PractitionerHiringListInfo> uniqueList = dataList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(
                // 利用 TreeSet 的排序去重构造函数来达到去重元素的目的
                // 根据hiringBasicInfoId去重
                () -> new TreeSet<>(Comparator.comparingLong(PractitionerHiringListInfo::getHiringBasicInfoId))), ArrayList::new));

        return uniqueList;
    }

    @Override
    public List<PractitionerHiringListInfo> practitionerApplyList(PractitionerHiringListRequestVO requestVO) {
        PageHelper.clearPage();//偶然遇到了这个问题，同一个查询结果一会是10个（预期），一会是真实个数（刷新/重启应用就又变成真实个数）  查看日志，发现了问题：结果为10个时查询SQL自动加上了Limit 10
        //体系查询调整，如果体系为S3，则需要查询它下面的所有子集
        PractitionerSubordinateInfo practitionerSubordinateInfo = new PractitionerSubordinateInfo();
        BeanUtils.copyProperties(requestVO,practitionerSubordinateInfo);
        practitionerSubordinateInfo.setInsurerBranchId(requestVO.getBranchId());
        List<Long> subsystemIdList = aclPractitionerSubordinateSystemDalService.getLongs(practitionerSubordinateInfo);
        List<PractitionerHiringListInfo> resultList = agmsHiringMapper.practitionerApplyList(requestVO.getStatus(), null,
        		requestVO.getBranchId(),
                requestVO.getDeptId(),
                subsystemIdList,
                requestVO.getName(),
        		requestVO.getStartDate(),
        		requestVO.getEndDate());
        return resultList;
    }
    
}
