package org.enfi.modules.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.enfi.common.util.PasswordUtil;
import org.enfi.common.util.RedisUtil;
import org.enfi.common.util.ThreadUtil;
import org.enfi.common.util.oConvertUtils;
import org.enfi.modules.system.entity.*;
import org.enfi.modules.system.mapper.IOaEmployeeVMapper;
import org.enfi.modules.system.model.SysDepartTreeModel;
import org.enfi.modules.system.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author WANG HAO
 * @since 2021-10-18
 */
@Service
public class OaEmployeeVServiceImpl extends ServiceImpl<IOaEmployeeVMapper, OaEmployeeV> implements IOaEmployeeVService {
    @Autowired
    private ISysDepartService sysDepartService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ISysUserDepartService sysUserDepartService;

    @Autowired
    private ISysUserRoleService sysUserRoleService;

    @Autowired
    private IDepartDataService iDepartDataService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public List<OaEmployeeV> findErpUserAll() {
        return this.list();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean syncDepAndSysUser() {
        iDepartDataService.importDep();
        importSysUserData();
        return true;
    }

    @Override
    public String importSysUserData() {
        List<OaEmployeeV> erpSysUserList = this.findErpUserAll().stream()
                .filter(distinctByKey(OaEmployeeV::getEmployeeNumber))
                .collect(Collectors.toList());
        sysUserDepartService.remove(new QueryWrapper<>());
        ThreadPoolExecutor theadPool = ThreadUtil.getTheadPool(10);
        for (OaEmployeeV user : erpSysUserList) {
            if (!StringUtils.isEmpty(user.getEmployeeNumber())) {
                theadPool.execute(() -> {
                    SysUser sysUser = new SysUser();
//            SysUser dataSysUser = sysUser.selectById(user.getEmployeeNumber());
//            boolean empty = oConvertUtils.isEmpty(dataSysUser);
                    sysUser.setId(user.getEmployeeNumber().trim());

                    sysUser.setUsername(user.getEmployeeNumber().trim());
                    sysUser.setPersonId(user.getPersonId().trim());
                    sysUser.setRealname(user.getLastName());
                    //通过部门id获取部门OrgCode
                    SysDepart sysDepart = sysDepartService.getBaseMapper().selectById((user.getOrganizationId()));
                    if (sysDepart != null) {
                        sysUser.setOrgCode(sysDepart.getOrgCode());

                    }

                    sysUser.setBirthday(user.getDateOfBirth());
                    sysUser.setSex(user.getSex().equals("男") ? 1 : user.getSex().equals("女") ? 2 : 0);
                    if (user.getEmailAddress() != null && user.getEmailAddress().contains("@")) {
                        //去除前后空格
                        sysUser.setEmail(user.getEmailAddress().trim());
                    }
                    sysUser.setTelephone(dealPhoneNum(user.getOfficeNumber()));
                    sysUser.setStatus(1);
                    sysUser.setActivitiSync(1);
                    sysUser.setDelFlag(0);


                    String salt = oConvertUtils.randomGen(8);
                    sysUser.setSalt(salt);
                    String passwordEncode = PasswordUtil.encrypt(sysUser.getUsername(), "xxjszx_test", salt);
                    sysUser.setPassword(passwordEncode);
                    sysUser.setWorkNo(user.getEmployeeNumber().trim());
                    if (user.getSecurityLevel() != null) {
                        if (Integer.parseInt(user.getSecurityLevel()) > 30) {
                            sysUser.setUserIdentity(2);
                            //根据部门id获取所有子部门id并储存
                            System.out.println(user.toString());
                            sysUser.setDepartIds(this.findDepartTreeByDepartId(user.getOrganizationId()));
                        } else {
                            sysUser.setUserIdentity(1);
                        }
                        sysUser.setSecurityLevel(Integer.parseInt(user.getSecurityLevel()));
                    }
                    sysUser.setCreateTime(new Date());
                    sysUser.setCreateBy("admin");  //默认创建者为系统用户
                    //储存用户部门关系
                    SysUserDepart sysUserDepart = new SysUserDepart(user.getOrganizationId() + "-" + user.getEmployeeNumber().trim()
                            , user.getEmployeeNumber().trim(), user.getOrganizationId());
                    sysUserDepartService.saveOrUpdate(sysUserDepart);
                    //保存用户与角色关系
                    SysUserRole sysUserRole = new SysUserRole();
                    sysUserRole.setId("normal_staff-" + user.getEmployeeNumber().trim());
                    sysUserRole.setUserId(user.getEmployeeNumber().trim());
                    sysUserRole.setRoleId("normal_staff");
                    sysUserRoleService.saveOrUpdate(sysUserRole);
                    //保存用户
                    userService.saveOrUpdate(sysUser);
                });
            }
        }
        ThreadUtil.waitThreadPoolCompleted(theadPool, "ERP用户同步完成");
        return "success";
    }


    /**
     * 处理座机号码格式
     *
     * @param telePhoneNum
     * @return
     */
    public String dealPhoneNum(String telePhoneNum) {
        if (telePhoneNum == null || telePhoneNum.isEmpty()) {
            return null;
        }
        //含 - 直接返回
        if (telePhoneNum.contains("-")) {
            return telePhoneNum;
        }
        //包含010尾号
        if (telePhoneNum.length() == 4) {
            return "010-6393" + telePhoneNum;
        } else if (telePhoneNum.startsWith("010")) {
            return "010-" + telePhoneNum.substring(3);
        } else {
            return "010-" + telePhoneNum;
        }
    }

    /**
     * 用于去重
     *
     * @param keyExtractor
     * @param <T>
     * @return
     */
    private static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
        Set<Object> seen = ConcurrentHashMap.newKeySet();
        return t -> seen.add(keyExtractor.apply(t));
    }

    /**
     * 根据某个部门id获取当前部门id及其所有下级部门id
     *
     * @param id
     * @return
     */
    private String findDepartTreeByDepartId(String id) {

        List<SysDepartTreeModel> departTreeModelList = null;

        Object o = redisUtil.get("allDepartTreeModel");
        if (o == null) {
            departTreeModelList = findDepartTreeInRedis();
        } else {
            departTreeModelList = JSONArray.parseArray(JSONArray.toJSONString(o), SysDepartTreeModel.class);
        }


//      SysDepartTreeModel result = departTreeModelList.stream()
//              .filter(s -> s.getKey().equals(id))
//              .collect(Collectors.toList()).get(0);

        Stack<SysDepartTreeModel> stack = new Stack<SysDepartTreeModel>();
        List<SysDepartTreeModel> collect = departTreeModelList.stream()
                .filter(s -> s.getKey().equals(id))
                .collect(Collectors.toList());

        if (collect.size() == 0) {
            return id;
        } else {
            stack.push(collect.get(0));
        }
        List<String> result = new ArrayList<>();
        while (!stack.isEmpty()) {
            SysDepartTreeModel treeModel = stack.pop();
            result.add(treeModel.getKey());
            if (treeModel.getChildren().size() > 0) {
                treeModel.getChildren().stream().forEach(
                        s -> stack.push(s)
                );
            }
        }

        return StringUtils.join(result, ",");

    }

    private List<SysDepartTreeModel> findDepartTreeInRedis() {
        //从redis中取值,避免每次操作都需要去访问数据库
        if (redisUtil.get("deaprtTree") == null) {
            redisUtil.set("deaprtTree", sysDepartService.queryTreeList());
        }
        /**
         *       得用JSONArray.toJSONString方法将从redis中获取的Object对象转为String字符串
         *       再进行转List数组操作 (不能用Object对象自带的toString方法,字符串中可能存在转义字符,转List数组时可能报错)
         */
        List<SysDepartTreeModel> departTreeModelList = JSONArray.parseArray(JSONArray.toJSONString(redisUtil.get("deaprtTree")), SysDepartTreeModel.class);

        Stack<SysDepartTreeModel> stack = new Stack<>();
        departTreeModelList.stream().forEach(
                s -> stack.push(s)
        );

        List<SysDepartTreeModel> result = getAllDepartTree(stack);
        if (redisUtil.get("allDepartTreeModel") == null) {
            redisUtil.set("allDepartTreeModel", result);
        }
        return result;
    }

    public List<SysDepartTreeModel> getAllDepartTree(Stack<SysDepartTreeModel> stack) {
        List<SysDepartTreeModel> result = new ArrayList<SysDepartTreeModel>();

        while (!stack.isEmpty()) {
            SysDepartTreeModel departTreeModel = stack.pop();
            result.add(departTreeModel);
            if (departTreeModel.getChildren().size() > 0) {
                departTreeModel.getChildren().stream().forEach(
                        s -> stack.push(s)
                );
            }
        }

        return result;
    }
}
