

package com.lideeyunji.core.framework.adapter;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.lideeyunji.tool.framework.yunji.annotation.lideeYunjiCache;
import com.lideeyunji.tool.framework.yunji.constant.lideeRedisConstants;
import com.lideeyunji.tool.framework.yunji.model.*;
import com.lideeyunji.tool.framework.security.core.LoginUser;
import com.lideeyunji.tool.framework.security.core.util.SecurityFrameworkUtils;
import com.lideeyunji.tool.framework.tenant.core.aop.TenantIgnore;
import com.lideeyunji.tool.framework.tenant.core.context.TenantContextHolder;
import com.lideeyunji.core.framework.mapper.AdapterMapper;
import com.lideeyunji.core.framework.utils.Func;
import com.lideeyunji.core.framework.utils.FuncWeb;
import com.lideeyunji.tool.framework.sql.SqlHelper;
import com.lideeyunji.tool.framework.sql.build.buildmodel.wrapper.SqlInfoQueryWrapper;
import com.lideeyunji.tool.framework.yunji.adapter.IlideeYunjiAdapter;
import com.lideeyunji.tool.framework.yunji.enums.DefaultDbFieldEnum;
import com.lideeyunji.tool.framework.yunji.params.lideeYunJiDeptParam;
import com.lideeyunji.tool.framework.yunji.params.lideeYunJiDictParam;
import com.lideeyunji.tool.framework.yunji.params.lideeYunJiUserParam;
import com.lideeyunji.tool.framework.yunji.utils.FuncBase;
import com.lideeyunji.tool.framework.yunji.utils.lideeYunJiUtils;
import com.lideeyunji.core.framework.service.IFrameSqlService;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 云玑源码适配器
 */
@Service
@Slf4j
public class FrameWorkAdapter implements IlideeYunjiAdapter {

    @Autowired
    private IFrameSqlService sqlService;

    @Autowired
    private AdapterMapper adapterMapper;

    //获取当前在线人id
    @Override
    public Long getOnlineUserId() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        return loginUserId;
    }

    //获取当前在线人账号
    @Override
    public String getOnlineUserName() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        String userName = adapterMapper.getUserName(loginUserId);
        return userName;
    }

    @lideeYunjiCache(cacheNames = "'"+ lideeRedisConstants.REDIS_ADAPTER+":getOnlineUserName:' + #userId", reflexClass = String.class)
    @Override
    public String getOnlineUserName(Long userId) {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        String userName = adapterMapper.getUserName(loginUserId);
        return userName;
    }

    @Override
    public String getOnlineUserNickName() {
        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
        return adapterMapper.getNickname(loginUserId);
    }

    @Override
    public Long getOnlineUserDeptId() {
        Long loginDeptId = SecurityFrameworkUtils.getLoginDeptId();
        return loginDeptId;
    }

    @Override
    public String getOnlineUserDeptName() {
        Long deptId = getOnlineUserDeptId();
        String deptName = adapterMapper.getDeptName(deptId);
        return deptName;
    }

    //获取当前在线角色列表
    @Override
    public List<String> getOnlineRoleCodeList() {
        Long onlineUserDeptId = this.getOnlineUserDeptId();
        Long onlineUserId = this.getOnlineUserId();
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        Long loginRoleId = loginUser.getLoginRoleId();

        List<String> roleCodeList = adapterMapper.getRoleCodeByUser(onlineUserId, onlineUserDeptId,loginRoleId);
        return roleCodeList;
    }

    @Override
    public List<Long> getOnlineRoleIdList() {
        Long onlineUserDeptId = this.getOnlineUserDeptId();
        Long onlineUserId = this.getOnlineUserId();
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        Long loginRoleId = loginUser.getLoginRoleId();

        List<Long> roleIdList = adapterMapper.getRoleIdByUser(onlineUserId, onlineUserDeptId,loginRoleId);
        return roleIdList;
    }

    //获取当前在线人id
    @Override
    public Long getTenantId() {
        //当前线程
        Long tenantId = TenantContextHolder.getTenantId();
        if (Func.isNotEmpty(tenantId) && tenantId > 0) {
            return tenantId;
        }
        //当前线程没有租户信息，则从登录用户获取
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (FuncBase.isNotEmpty(loginUser)) {
            return loginUser.getTenantId();
        }
        return -1L;
    }

    //获取所有租户列表
    @Override
    public List<LideeTenant> getTenantList() {
        List<String> selectList = new ArrayList<>();
        selectList.add("id");
        selectList.add("name");

        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .setTableName("system_tenant")
                .select(selectList, true)
                .setWhere(where -> {
                    where.eq("is_deleted", 0);
                    where.eq("status", 0);
                }).build();
        List<Map<String, Object>> tenantList = sqlService.getDataListByPlus(wrapper);

        return tenantList.stream()
                .map(tenantMap -> {
                    String id = lideeYunJiUtils.getMap2Str(tenantMap, "id");
                    String name = lideeYunJiUtils.getMap2Str(tenantMap, "name");
                    LideeTenant lideeTenant = new LideeTenant();
                    lideeTenant.setTenantId(id);
                    lideeTenant.setTenantName(name);
                    return lideeTenant;
                })
                .collect(Collectors.toList());
    }

    //获取字典列表
    @Override
    public List<lideeYunjiDict> getDictList(lideeYunJiDictParam param) {
        List<lideeYunjiDict> resultList = new ArrayList<>();
        List<String> dictCodeList = param.getDictCodeList();
        Map<String, lideeYunJiDictParam.DictCodeDataParam> paramMap = FuncBase.isEmpty(param.getParamMap()) ? new HashMap<>() : param.getParamMap();

        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .setTableName("system_dict_type")
                .setWhere(where -> {
                    where.eq("is_deleted", 0);
                    where.eq("status", 0);
                    where.in("type", dictCodeList);
                }).build();
        List<Map<String, Object>> typeList = sqlService.getDataListByPlus(wrapper);

        typeList.stream()
                .map(typeMap -> {
                    String code = lideeYunJiUtils.getMap2Str(typeMap, "type");
                    lideeYunJiDictParam.DictCodeDataParam dictCodeDataParam = paramMap.get(code);

                    List<String> dictDataLabelList = FuncBase.isNotEmpty(dictCodeDataParam) ? dictCodeDataParam.getDictDataLabelList() : Collections.emptyList();
                    List<String> dictDataValueList = FuncBase.isNotEmpty(dictCodeDataParam) ? dictCodeDataParam.getDictDataValueList() : Collections.emptyList();

                    SqlInfoQueryWrapper.Wrapper wrapperData = SqlHelper.getQueryWrapper()
                            .setTableName("system_dict_data")
                            .select("value", "label")
                            .setWhere(where -> {
                                where.eq("is_deleted", 0);
                                where.eq("status", 0);
                                where.eq("dict_type", code);
                                where.in("label", dictDataLabelList);
                                where.in("value", dictDataValueList);
                            })
                            .orderByAsc("sort")
                            .build();
                    List<Map<String, Object>> dataList = sqlService.getDataListByPlus(wrapperData);

                    List<lideeYunjiDict.DictData> list = dataList.stream()
                            .map(tmpMap -> {
                                String value = lideeYunJiUtils.getMap2Str(tmpMap, "value");
                                String label = lideeYunJiUtils.getMap2Str(tmpMap, "label");

                                lideeYunjiDict.DictData data = new lideeYunjiDict.DictData();
                                data.setLabel(label);
                                data.setVal(value);
                                return data;
                            })
                            .collect(Collectors.toList());

                    lideeYunjiDict dict = new lideeYunjiDict();
                    dict.setDataList(list);
                    dict.setDictCode(code);
                    return dict;
                })
                .forEach(resultList::add);

        return resultList;
    }

    //获取部门列表
    @Override
    public List<lideeYunjiDept> getDeptList(lideeYunJiDeptParam param) {

        String deptName = param.getDeptName();//部门名称搜索
        String type = Func.isEmpty(param.getType()) ? "all" : param.getType();
        List<Long> deptIdList = new ArrayList<>();//部门id列表,为空则查所有
        if (Func.equals(type, "now")) {//本级
            deptIdList.add(this.getOnlineUserDeptId());
        } else if (Func.equals(type, "sub")) {//本级以及下级
            deptIdList = this.getChildDeptIdList(this.getOnlineUserDeptId(), true);
        } else if (Func.equals(type, "all_sub")) {//所有下级
            deptIdList = this.getChildDeptIdList(this.getOnlineUserDeptId(), false);
        } else if (Func.equals(type, "direct_sub")) {//直接下级
            deptIdList = this.getDirectChildDeptIdList(this.getOnlineUserDeptId());
        }

        List<Long> finalDeptIdList = deptIdList;
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .select("id", "parent_id", "name")
                .setTableName("system_dept")
                .setWhere(where -> {
                    where.in(Func.isNotEmpty(finalDeptIdList), "id", finalDeptIdList);
                    where.like(FuncBase.isNotEmpty(deptName), "name", deptName);
                    where.eq("is_deleted", 0);
                })
                .orderByAsc("sort")
                .build();
        List<Map<String, Object>> deptList = sqlService.getDataListByPlus(wrapper);

        List<lideeYunjiDept> resultList = deptList.stream()
                .map(deptMap -> {
                    String id = lideeYunJiUtils.getMap2Str(deptMap, "id");
                    String pid = lideeYunJiUtils.getMap2Str(deptMap, "parent_id");
                    String name = lideeYunJiUtils.getMap2Str(deptMap, "name");

                    lideeYunjiDept dept = new lideeYunjiDept();
                    dept.setDeptId(id);
                    dept.setDeptPid(pid);
                    dept.setDeptName(name);
                    return dept;
                })
                .collect(Collectors.toList());
        return resultList;
    }

    //获取所有角色列表
    @Override
    public List<lideeYunJiRole> getRoleList() {
        Long tenantId = TenantContextHolder.getTenantId();
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .select("id", "name")
                .setTableName("system_role")
                .setWhere(where -> {
                    where.in("is_deleted", 0);
                    where.eq("tenant_id", tenantId);
                })
                .orderByAsc("sort")
                .build();
        List<Map<String, Object>> roleList = sqlService.getDataListByPlus(wrapper);

        List<lideeYunJiRole> resultList = roleList.stream()
                .map(roleMap -> {
                    String id = lideeYunJiUtils.getMap2Str(roleMap, "id");
                    String name = lideeYunJiUtils.getMap2Str(roleMap, "name");

                    lideeYunJiRole role = new lideeYunJiRole();
                    role.setRoleId(id);
                    role.setRoleName(name);
                    return role;
                })
                .collect(Collectors.toList());
        return resultList;
    }

    //获取用户详情
    @TenantIgnore
    @Override
    public List<Map<String, Object>> getUserInfoList(List<Long> userIdList) {
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .select("id", "username", "nickname", "mobile", "sex")
                .setTableName("system_users")
                .setWhere(where -> {
                    where.in("id", userIdList);
                })
                .build();
        List<Map<String, Object>> dataList = sqlService.getDataListByPlus(wrapper);
        return dataList;
    }

    //回显用户
    @TenantIgnore
    @Override
    public List<Map<String, Object>> getUserViewList(List<Long> userIdList) {
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .select("id", "nickname")
                .setTableName("system_users")
                .setWhere(where -> {
                    where.in("id", userIdList);
                })
                .build();
        List<Map<String, Object>> dataList = sqlService.getDataListByPlus(wrapper);
        return dataList;
    }

    //回显部门
    @TenantIgnore
    @Override
    public List<Map<String, Object>> getDeptViewList(List<Long> deptIdList) {
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .select("id", "name")
                .setTableName("system_dept")
                .setWhere(where -> {
                    where.in("id", deptIdList);
                })
                .build();
        List<Map<String, Object>> dataList = sqlService.getDataListByPlus(wrapper);
        return dataList;
    }


    //获取用户分页列表
    @Override
    public Object getUserPage(Integer pageNo, Integer pageSize, lideeYunJiUserParam param) {
        Page page = FuncWeb.getPage(pageNo, pageSize);
        Long deptId = param.getDeptId();
        Long roleId = param.getRoleId();
        String type = param.getType();//all  now sub

        String nickName = param.getNickName();
        String mobile = param.getMobile();
        List<String> fieldList = param.getFieldList();

        List<Long> deptIdList = new ArrayList<>();//部门id列表
        if (Func.isEmpty(deptId)) {//部门为空的时候，type才生效
            if (Func.equals(type, "now")) {//本级
                deptIdList.add(this.getOnlineUserDeptId());
            } else if (Func.equals(type, "sub")) {//本级以及下级
                deptIdList = this.getChildDeptIdList(this.getOnlineUserDeptId(), true);
            } else if (Func.equals(type, "all_sub")) {//所有下级
                deptIdList = this.getChildDeptIdList(this.getOnlineUserDeptId(), false);
            } else if (Func.equals(type, "direct_sub")) {//直接下级
                deptIdList = this.getDirectChildDeptIdList(this.getOnlineUserDeptId());
            }
        } else {//指定部门
            deptIdList.add(deptId);
        }


        Map<String, Object> params = new HashMap<>();
        if(Func.isNotEmpty(nickName)){
            params.put("nickName", "%"+nickName+"%");
        }

        if(Func.isNotEmpty(mobile)){
            params.put("mobile", "%"+mobile+"%");
        }

        IPage<lideeYunJiUser> pages = null;
        if (Func.isNotEmpty(roleId)) {//说明有选择了角色
            pages = adapterMapper.getUserPageByRoleId(getTenantId(), page, roleId, deptIdList, params);
        } else {
            pages = adapterMapper.getUserPageByDeptId(getTenantId(), page, deptIdList, params);
        }
        //处理角色和职位
        Map<String, String> userIdAndDeptName = getUserIdAndDeptName(getTenantId(), deptIdList);
        Map<String, String> userIdAndPostName = getUserIdAndPostName(getTenantId());
        Map<String, String> sexDictMap = getDictData("system_user_sex");

        pages.getRecords().forEach(record -> {
            String userId = record.getUserId();
            String deptName = userIdAndDeptName.get(userId);
            record.setDeptName(deptName);

            String postName = userIdAndPostName.get(userId);
            record.setPost(postName);

            String sex = record.getSex();
            record.setSex(sexDictMap.get(sex));
        });
        if (Func.isEmpty(fieldList)) {//查所有
            return pages;
        }

        //存在自定义列
        Map<String, Consumer<lideeYunJiUser>> fieldSetters = new HashMap<>();
        fieldSetters.put("userId", user -> user.setUserId(null));
        fieldSetters.put("nickName", user -> user.setNickName(null));
        fieldSetters.put("mobile", user -> user.setMobile(null));
        fieldSetters.put("email", user -> user.setEmail(null));
        fieldSetters.put("sex", user -> user.setSex(null));
        fieldSetters.put("post", user -> user.setPost(null));
        fieldSetters.put("avatar", user -> user.setAvatar(null));
        fieldSetters.put("deptName", user -> user.setDeptName(null));
        // 为其他字段添加更多的条目

        List<lideeYunJiUser> records = pages.getRecords();
        records.stream().peek(user -> fieldSetters.forEach((fieldName, setter) -> {
            if (!fieldList.contains(fieldName)) {
                setter.accept(user);
            }
        }))
                .collect(Collectors.toList());
        return pages;
    }


    //初始化-新增数据默认项
    @Override
    public void initSaveDefaultData(Map<String, Object> map) {
        //默认值由系统赋值，不做修改
        map.remove(DefaultDbFieldEnum.CREATE_USER.getFieldCode());
        map.remove(DefaultDbFieldEnum.CREATE_TIME.getFieldCode());
        map.remove(DefaultDbFieldEnum.CREATE_DEPT.getFieldCode());
        map.remove(DefaultDbFieldEnum.IS_DELETED.getFieldCode());
        map.remove(DefaultDbFieldEnum.TENANT_ID.getFieldCode());
        map.remove(DefaultDbFieldEnum.UPDATE_USER.getFieldCode());
        map.remove(DefaultDbFieldEnum.UPDATE_TIME.getFieldCode());

        DateTime now = DateUtil.date();

        if (FuncBase.isEmpty(map.get(DefaultDbFieldEnum.ID.getFieldCode()))) {
            map.put(DefaultDbFieldEnum.ID.getFieldCode(), IdWorker.getId());
        }

        map.put(DefaultDbFieldEnum.CREATE_USER.getFieldCode(), this.getOnlineUserId());
        map.put(DefaultDbFieldEnum.CREATE_TIME.getFieldCode(), now);
        map.put(DefaultDbFieldEnum.CREATE_DEPT.getFieldCode(), this.getOnlineUserDeptId());
        map.put(DefaultDbFieldEnum.IS_DELETED.getFieldCode(), 0);
        map.put(DefaultDbFieldEnum.TENANT_ID.getFieldCode(), this.getTenantId());
    }

    //初始化-修改数据默认项
    @Override
    public void initUpdateDefaultData(Map<String, Object> map) {
        //默认值由系统赋值，不做修改
        map.remove(DefaultDbFieldEnum.CREATE_USER.getFieldCode());
        map.remove(DefaultDbFieldEnum.CREATE_TIME.getFieldCode());
        map.remove(DefaultDbFieldEnum.CREATE_DEPT.getFieldCode());
        map.remove(DefaultDbFieldEnum.IS_DELETED.getFieldCode());
        map.remove(DefaultDbFieldEnum.TENANT_ID.getFieldCode());
        map.remove(DefaultDbFieldEnum.UPDATE_USER.getFieldCode());
        map.remove(DefaultDbFieldEnum.UPDATE_TIME.getFieldCode());

        DateTime now = DateUtil.date();
        map.put(DefaultDbFieldEnum.UPDATE_USER.getFieldCode(), this.getOnlineUserId());
        map.put(DefaultDbFieldEnum.UPDATE_TIME.getFieldCode(), now);

    }

    /**
     * 获取所有子部门
     *
     * @param id
     * @param includeNowFlag true=包括本级
     * @return
     */
    private List<Long> getChildDeptIdList(Long id, boolean includeNowFlag) {
        List<Long> children = new LinkedList<>();//子集
        children.add(-1L);//保证不会跳过这个过滤条件
        if (includeNowFlag) {
            children.add(id);
        }

        // 遍历每一层
        List<Long> parentIdList = new ArrayList<>();
        parentIdList.add(id);

        for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下，存在死循环

            List<Long> finalParentIdList = parentIdList;
            SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                    .select("id")
                    .setTableName("system_dept")
                    .setWhere(where -> {
                        where.eq("is_deleted", 0);
                        where.in("parent_id", finalParentIdList);
                    })
                    .build();
            List<Map<String, Object>> deptList = sqlService.getDataListByPlus(wrapper);

            // 1. 如果没有子部门，则结束遍历
            if (Func.isEmpty(deptList)) {
                break;
            }

            List<Long> tmpIdList = deptList.stream()
                    .map(deptMap -> Func.getMap2Long(deptMap, "id"))
                    .filter(Objects::nonNull)
                    .collect(Collectors.toCollection(ArrayList::new));

            children.addAll(tmpIdList);//存入到总集合里面
            parentIdList = tmpIdList;//进行下一轮
        }
        return children;
    }


    //获取直接下级
    private List<Long> getDirectChildDeptIdList(Long id) {
        List<Long> children = new LinkedList<>();//子集
        children.add(-1L);

        // 遍历每一层
        List<Long> parentIdList = new ArrayList<>();
        parentIdList.add(id);
        List<Long> finalParentIdList = parentIdList;
        SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper()
                .select("id")
                .setTableName("system_dept")
                .setWhere(where -> {
                    where.eq("is_deleted", 0);
                    where.in("parent_id", finalParentIdList);
                })
                .build();
        List<Map<String, Object>> deptList = sqlService.getDataListByPlus(wrapper);

        // 1. 如果没有子部门，则结束遍历
        if (Func.isEmpty(deptList)) {
            return children;
        }

        List<Long> tmpIdList = deptList.stream()
                .map(deptMap -> Func.getMap2Long(deptMap, "id"))
                .filter(Objects::nonNull)
                .collect(Collectors.toCollection(ArrayList::new));

        children.addAll(tmpIdList);//存入到总集合里面
        return children;
    }

    //获取用户id和部门名称  1=开发部，测试部
    private Map<String, String> getUserIdAndDeptName(Long tenantId, List<Long> deptIdList) {
        List<Map<String, Object>> dataMapList = adapterMapper.getUserIdAndDeptName(tenantId, deptIdList);
        Map<String, String> userIdAndDeptNameMap = new HashMap<>();
        //key=id  value=逗号拼接
        for (Map<String, Object> dataMap : dataMapList) {
            String userId = Func.getMap2Str(dataMap, "user_id");
            String deptName = Func.getMap2Str(dataMap, "dept_name");
            String val = userIdAndDeptNameMap.get(userId);
            if (FuncBase.isEmpty(val)) {
                userIdAndDeptNameMap.put(userId, deptName);
                continue;
            }//去重
            List<String> strList = Func.toStrList(val);
            if (strList.contains(deptName)) {
                continue;
            }
            userIdAndDeptNameMap.put(userId, val + "," + deptName);
        }
        return userIdAndDeptNameMap;
    }

    private Map<String, String> getUserIdAndPostName(Long tenantId) {
        List<Map<String, Object>> dataMapList = adapterMapper.getUserIdAndPostName(tenantId);
        Map<String, String> userIdAndPostNameMap = new HashMap<>();
        //key=id  value=逗号拼接
        for (Map<String, Object> dataMap : dataMapList) {
            String userId = Func.getMap2Str(dataMap, "user_id");
            String postName = Func.getMap2Str(dataMap, "post_name");
            String val = userIdAndPostNameMap.get(userId);
            if (FuncBase.isEmpty(val)) {
                userIdAndPostNameMap.put(userId, postName);
                continue;
            }//去重
            List<String> strList = Func.toStrList(val);
            if (strList.contains(postName)) {
                continue;
            }
            userIdAndPostNameMap.put(userId, val + "," + postName);
        }
        return userIdAndPostNameMap;
    }

    //获取字典map
    private Map<String,String> getDictData(String dictType){
        List<Map<String, Object>> dictData = adapterMapper.getSysDictMap(dictType);
        return dictData.stream().collect(Collectors.toMap(dataMap -> Func.getMap2Str(dataMap, "value"), dataMap -> Func.getMap2Str(dataMap, "label")));
    }
}