package com.lz.modules.job.business;

import com.google.common.collect.Lists;
import com.lz.common.emun.WorkMsgTypeEnum;
import com.lz.common.utils.DateUtils;
import com.lz.common.utils.DingTalkUtil;
import com.lz.common.utils.R;
import com.lz.modules.app.dao.StaffDao;
import com.lz.modules.app.entity.StaffEntity;
import com.lz.modules.app.entity.StaffOccupationEntity;
import com.lz.modules.app.entity.StaffSimpleInfo;
import com.lz.modules.app.service.DepartmentsService;
import com.lz.modules.app.service.DepartmentsStaffRelateService;
import com.lz.modules.app.service.StaffOccupationService;
import com.lz.modules.app.service.StaffService;
import com.lz.modules.flow.entity.FlowRecord;
import com.lz.modules.flow.service.FlowRecordService;
import com.lz.modules.job.model.responseBo.DepartmentInfosBo;
import com.lz.modules.job.model.responseBo.DepartmentStaffBo;
import com.lz.modules.sys.dao.SysUserTokenDao;
import com.lz.modules.sys.entity.SysUserTokenEntity;
import com.lz.modules.sys.entity.app.ResultRecord;
import com.lz.modules.sys.service.app.ResultRecordService;
import com.lz.modules.third.entity.ThirdAppConfig;
import com.lz.modules.third.service.ThirdAppConfigService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author fumeiai
 * @date 2019-05-29 17:06
 * @Description 钉钉同步业务
 * @注意 本内容仅限于杭州霖梓网络科技有限公司内部传阅，禁止外泄以及用于其他的商业目的
 */
@Component(value = "dingtalkBusiness")
public class DingtalkBusiness {
    protected final static org.slf4j.Logger logger = LoggerFactory.getLogger(DingtalkBusiness.class);
    //token过期时间12小时
    private final static int EXPIRE = 3600 * 12;
    @Autowired
    DingTalkUtil dingTalkUtil;

    @Resource
    DepartmentsService departmentsService;

    @Resource
    DepartmentsStaffRelateService departmentsStaffRelateService;

    @Resource
    StaffService staffService;

    @Resource
    StaffOccupationService staffOccupationService;

    @Autowired
    ThirdAppConfigService thirdAppConfigService;

    @Autowired
    private SysUserTokenDao sysUserTokenDao;

    @Autowired
    private ResultRecordService resultRecordService;

    @Autowired
    private FlowRecordService flowRecordService;

    @Resource
    StaffDao staffDao;


    @Value("${dingtalk.appid}")
    private String appid;

    /**
     * 获取组织架构信息并录入到数据库
     */
//    @DataSource(name = DataSourceNames.FOUR)
    public void getDingTalkepartmentsIntoData(String appid) {

        /*List<StaffEntity> staffEntityList = staffDao.selectByRang("1004");//飞书数据更新为钉钉数据
        for (StaffEntity staff:staffEntityList
             ) {
            List<StaffEntity> list = staffDao.selectByName(staff.getName());
            if(list.size() > 0){
                StaffEntity staff1 = list.get(0);
                if(staff.getId().intValue() != staff1.getId().intValue()){
                    staff1.setJobNumber(staff.getJobNumber());
                    staff1.setAvatar(staff.getAvatar());
                    staff1.setEmployeeId(staff.getEmployeeId());
                    staff1.setOpenId(staff.getOpenId());
                    staff1.setUnionId(staff.getUnionId());


                    staffDao.deleteById(staff.getId());
                    staffDao.updateStaff(staff1);
                }

            }


        }
        return;*/
        //获取Token
        String token = dingTalkUtil.getAccessToken(appid);
        if(token != null && token.length() > 0){
            //获取所有的部门详情
            Map<String, DepartmentInfosBo> departmentInfosBos = dingTalkUtil.getDepartmentDetails(token, "1");
            if(departmentInfosBos.size() > 0){
                //更新数据库中的部门相关信息
                //departmentsService.updateDepartmentInfos(departmentInfosBos);
                //删除原有的对应关系下面在更新
                departmentsStaffRelateService.deleteAllRelates();
                //未在飞书组织架构里的成员，置为离职(全部置为离职，再把在职的恢复)
                staffOccupationService.updateAllOccupation();
                //获取飞书部门对应的用户详情
                for (String key : departmentInfosBos.keySet()) {
                    DepartmentInfosBo departmentInfo = departmentInfosBos.get(key);
                    //获取部门用户详情
                    List<DepartmentStaffBo> staffs = dingTalkUtil.getDepartmentStaffDetails(token, departmentInfo.getId());
                    logger.info("=============================" + departmentInfo.getName() + "================================");

                    //departmentInfo.setMemberCount(staffs.size());//设置部门人数，钉钉没有返回部门人数，只能这样设置
                    //计算父类的
                    DepartmentInfosBo integer = departmentInfo;
                    while(!integer.getParentId().equals("1")){
                        integer = departmentInfosBos.get(integer.getParentId());
                        if(integer.getMemberCount() == null){
                            integer.setMemberCount(0);
                        }
                        integer.setMemberCount(integer.getMemberCount() + staffs.size());

                    }
                    //获取自己的
                    if(departmentInfo.getMemberCount() == null){
                        departmentInfo.setMemberCount(0);
                    }
                    departmentInfo.setMemberCount(departmentInfo.getMemberCount() + staffs.size());

                    if(staffs.size() > 0){
                        //循环录入到员工信息表中
                        if(staffService.updateStaffsInfo(staffs)){
                            //加入到部门和员工关系表，同时更新leader关系
                            departmentsStaffRelateService.addRelateInfos(departmentInfo.getId(), staffs);
                            //录入员工职业信息表
                            enterStaffOccupationInfos(staffs);
                        }


                    }
                }
                for (String key : departmentInfosBos.keySet()) {
                    DepartmentInfosBo departmentInfo = departmentInfosBos.get(key);
                    departmentsService.updateDepartmentInfo(departmentInfo);
                }

            }else{
                logger.info("部门信息为空");
            }
        }
    }



    public void enterStaffOccupationInfos(List<DepartmentStaffBo> staffs) {
        List<StaffOccupationEntity> StaffOccupations = Lists.newArrayList();
        for (DepartmentStaffBo departmentStaffBo : staffs) {
            StaffEntity staffEntity = staffService.getStaffInfoByOpenId(departmentStaffBo.getOpenId());
            Long staffId = staffEntity.getId();
            StaffOccupationEntity staffOccupationEntity = staffOccupationService.getStaffOccupationByStaffId(staffId);
            if (staffOccupationEntity == null) {
                StaffOccupationEntity staffOccupation = new StaffOccupationEntity();
                staffOccupation.setStaffId(staffId);
                staffOccupation.setPosition(departmentStaffBo.getPosition());//职位信息
                staffOccupation.setEmployeeNo(departmentStaffBo.getEmployeeNo());
                staffOccupation.setStaffNo(departmentStaffBo.getEmployeeNo());//钉钉的员工工号
                staffOccupation.setStaffType(departmentStaffBo.getEmployeeType());
                staffOccupation.setStaffStatus(departmentStaffBo.getStatus());
                staffOccupation.setEntryTime(DateUtils.getCurrentDate());
                StaffOccupations.add(staffOccupation);
            } else {
                staffOccupationService.updateStatusByStaff(staffId, departmentStaffBo);//更新职位信息，工号信息
            }
        }
        if (StaffOccupations.size() > 0) {
            staffOccupationService.saveBatch(StaffOccupations);
        }
    }

    public String sendWorkMSG(String appid, Long fromStaffid, long toStaffid, int type) {
        //获取Token
        StaffEntity toStaffEntity = staffService.selectStaffById(toStaffid);
        StaffEntity fromStaffEntity = staffService.selectStaffById(fromStaffid);

        WorkMsgTypeEnum workMsgTypeEnum = WorkMsgTypeEnum.findRoleTypeByCode(type);
        return sendWorkMSGByEntity(appid, fromStaffEntity, toStaffEntity, workMsgTypeEnum, "https://www.baidu.com");
    }


    //流程流转发送消息
    public String sendWorkMSGWithAsyn(Long resultRecordId , int type) {
        ResultRecord resultRecord = resultRecordService.selectResultRecordById(resultRecordId);
        if(resultRecord != null){
            StaffSimpleInfo fromStaff = staffService.selectStaffSimpleInfo(resultRecord.getStaffId());
            List<StaffSimpleInfo> toStaffids;
            if(type == WorkMsgTypeEnum.REJECT.getType()){
                toStaffids = new ArrayList<>();
                toStaffids.add(fromStaff);
                sendWorkMSGWithAsyn(fromStaff, toStaffids, WorkMsgTypeEnum.REJECT.getType());
            }else{
                List<FlowRecord> flowRecords =
                        flowRecordService.selectFlowRecordByRecordIdStatus(resultRecordId, 2);
                List<Long> ids = flowRecords.stream().map(new Function<FlowRecord, Long>() {
                    @Override
                    public Long apply(FlowRecord flowRecord) {
                        return flowRecord.getApprovalStaffId();
                    }
                }).collect(Collectors.toList());
                toStaffids = staffService.selectStaffSimpleInfos(ids);
                sendWorkMSGWithAsyn(fromStaff, toStaffids, WorkMsgTypeEnum.PROCESS.getType());
            }



        }
        return "error";
    }


        public String sendWorkMSGWithAsyn(StaffSimpleInfo fromStaff, List<StaffSimpleInfo> toStaffids, int type) {
        if(toStaffids.size() > 0){
            if (toStaffids.get(0).getEmployeeId() == null || toStaffids.get(0).getEmployeeId().length() == 0) {
                //查询第三方id
                List<Long> ids = toStaffids.stream().map(new Function<StaffSimpleInfo, Long>() {
                    @Override
                    public Long apply(StaffSimpleInfo staffSimpleInfo) {
                        return staffSimpleInfo.getId();
                    }
                }).collect(Collectors.toList());
                List<StaffSimpleInfo> staffSimpleInfos = staffService.selectStaffSimpleInfos(ids);
                Map<Long, StaffSimpleInfo> map = toStaffids.stream().collect(Collectors.toMap(StaffSimpleInfo::getId, e -> e));
                for (StaffSimpleInfo staff : staffSimpleInfos
                ) {
                    StaffSimpleInfo staff1 = map.get(staff.getId());
                    staff1.setEmployeeId(staff1.getEmployeeId());
                }
            }
            WorkMsgTypeEnum workMsgTypeEnum = WorkMsgTypeEnum.findRoleTypeByCode(type);

            ThreadSendMessage threadSendMessage = new ThreadSendMessage(fromStaff, toStaffids, workMsgTypeEnum, appid);
            Thread thread = new Thread(threadSendMessage);
            thread.start();
            return "OK";
        }
        return "error";
    }


    public String sendWorkMSGWithAsyn(List<StaffSimpleInfo> toStaffids, int type) {

        return sendWorkMSGWithAsyn(null, toStaffids, type);

    }

    public String sendWorkMSGByEntity(String appid, StaffEntity fromStaffEntity, StaffEntity toStaffEntity,
                                      WorkMsgTypeEnum workMsgTypeEnum, String url){
        if(toStaffEntity != null && fromStaffEntity != null){

            ThirdAppConfig thirdAppConfig = thirdAppConfigService.getByAppId(appid);
            String token = dingTalkUtil.getAccessTokenWitchEntity(thirdAppConfig);
            if(token != null && token.length() > 0){
                //下面防止第二次发送消息时钉钉不推送
                if(url.contains("?")){
                    url += "&halokit=" + System.currentTimeMillis();
                }else{
                    url += "?halokit=" + System.currentTimeMillis();
                }
                url = URLEncoder.encode(url);
               /* url = "dingtalk://dingtalkclient/action/openapp?corpid=" + thirdAppConfig.getCorpId() +
                        "&container_type=work_platform&app_id=0_" + appid + "&redirect_type=jump&redirect_url=" + url;*/

                url = "dingtalk://dingtalkclient/page/link?pc_slide=true&url=" + url;

                String content = workMsgTypeEnum.getContent().replace("@", fromStaffEntity.getName());
                return dingTalkUtil.sendSingleActionCardMSG(appid, toStaffEntity, workMsgTypeEnum.getTitle(),
                        content, workMsgTypeEnum.getBtnText(), url, token);
            }else{
                return "token无效";
            }
        }
        return "无相关人员信息";
    }

    public R login(String code, String appid) {
        logger.info("钉钉登录appid{}", appid);
        String token = dingTalkUtil.getAccessToken(appid);
        if(token != null && token.length() > 0){
            return dingTalkUtil.getUserIdByCode(code, token);
        }
        return R.error("授权失败，未授权");
    }

    public R luck(String code, String appid, Long luckId) {
        String token = dingTalkUtil.getAccessToken(appid);
        if(token != null && token.length() > 0){
            return dingTalkUtil.luck(code, token, luckId);
        }
        return R.error("授权失败，未授权");
    }

    public R jump(String code) {
        SysUserTokenEntity tokenEntity = sysUserTokenDao.getByTokenCode(code);
        if(tokenEntity != null){//token不存在或者超过2分钟
            long big = System.currentTimeMillis() - tokenEntity.getCodeTime().getTime();
            logger.info("跳转的时间差{}", big);
            if(big < 120000L){
                //这里不更新时间了
                tokenEntity.setTokenCode("");
                sysUserTokenDao.updateById(tokenEntity);
                long expire = tokenEntity.getExpireTime().getTime() - System.currentTimeMillis();
                return R.ok().put("token", tokenEntity.getToken()).put("expire", expire);
            }

        }
        logger.info("token的token_code不存在");
        return R.error("未授权登录");
    }

    public class ThreadSendMessage implements Runnable{
        List<StaffSimpleInfo> toStaffids;
        StaffSimpleInfo fromStaff = null;
        WorkMsgTypeEnum workMsgTypeEnum;
        String appid;
        String hostUrl = "https://lzmanagement.ldxinyong.com/digitization/dingTalkLogin";
        public ThreadSendMessage(StaffSimpleInfo fromStaff, List<StaffSimpleInfo> toStaffids, WorkMsgTypeEnum typeEnum, String appid){
            this.toStaffids = toStaffids;
            workMsgTypeEnum = typeEnum;
            this.fromStaff = fromStaff;
            this.appid = appid;
        }

        @Override
        public void run() {
            logger.info("开始批量推送消息，数量{}, appid", toStaffids.size(), appid);
            ThirdAppConfig thirdAppConfig = thirdAppConfigService.getByAppId(appid);
            String token = dingTalkUtil.getAccessTokenWitchEntity(thirdAppConfig);
            for (StaffSimpleInfo info:toStaffids
                 ) {
                if(token != null && token.length() > 0){
                    //下面防止第二次发送消息时钉钉不推送
                    String url = hostUrl;
                    if(url.contains("?")){
                        url += "&halokit=" + System.currentTimeMillis();
                    }else{
                        url += "?halokit=" + System.currentTimeMillis();
                    }
                    url += ("&detail=1&id=" + info.getRecordId());
                    url = URLEncoder.encode(url);


                    url = "dingtalk://dingtalkclient/action/openapp?corpid=" + thirdAppConfig.getCorpId() +
                           "&container_type=work_platform&app_id=0_" +
                            appid + "&redirect_type=jump&redirect_url=" + url;
                    String content = null;
                    if(fromStaff == null){
                        content = workMsgTypeEnum.getContent().replace("@", info.getName());
                    }else{
                        if(fromStaff.getId() == info.getId()){
                            content = workMsgTypeEnum.getContent().replace("@", "您");
                        }else{
                            content = workMsgTypeEnum.getContent().replace("@", fromStaff.getName());
                        }

                    }

                    StaffEntity entity = new StaffEntity();
                    entity.setId(info.getId());
                    entity.setEmployeeId(info.getEmployeeId());
                    dingTalkUtil.sendSingleWorkMSG(appid, entity, workMsgTypeEnum.getTitle(),
                            content, workMsgTypeEnum.getBtnText(), url, token);
                }else{
                    logger.info("ThreadSendMessage token无效"); ;
                }
            }
        }
    }
}
