/*
 * Copyright (c) 2023 codvision.com All Rights Reserved.
 */

package com.codvision.auth.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.codvision.auth.entity.*;
import com.codvision.auth.mapper.OrgPropertyMapper;
import com.codvision.auth.mapper.SysRoleMapper;
import com.codvision.auth.mapper.SysUserMapper;
import com.codvision.auth.mapper.UserOrgRoleMapper;
import com.codvision.auth.service.IDingUserService;
import com.codvision.auth.service.IOrgService;
import com.codvision.auth.support.DingHelper;
import com.codvision.base.service.ISysConfigService;
import com.codvision.commoncore.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * 钉钉用户业务实现
 *
 * @author lingee
 * @since 2024/4/11
 */
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class DingUserServiceImpl implements IDingUserService {

    @Resource
    private IOrgService orgService;

    @Resource
    private OrgPropertyMapper orgPropertyMapper;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private UserOrgRoleMapper userOrgRoleMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private DingHelper dingHelper;

    @Resource
    private BCryptPasswordEncoder bCryptEncode;

    @Resource
    private ISysConfigService configService;

    @Override
    public void syncDepartment() {
        log.info("开始同步钉钉组织架构");
        try {
            syncDept(1, 2);
        } catch (Exception e) {
            log.error("同步钉钉组织架构失败", e);
            throw new BusinessException("同步钉钉组织架构失败:" + e.getMessage());
        }
    }

    @Override
    public void syncUser(String roleCode) {
        List<Org> orgList = orgService.list();
        if (CollUtil.isEmpty(orgList)) {
            throw new BusinessException("组织信息为空，请先同步组织");
        }
        orgService.list().forEach(
                org -> {
                    try {
                        log.info("======>>>>>>组织名称：" + org.getName());
                        syncDepartUser(Long.parseLong(org.getRefOid()), roleCode);
                    } catch (Exception e) {
                        throw new RuntimeException(e);
                    }
                }
        );
    }

    public void syncDepartUser(long deptId, String roleCode) throws Exception {
        // 用户绑定角色编码不存在创建角色
        if (StringUtils.isBlank(roleCode)) {
            throw new BusinessException("角色编码不能为空");
        }
        SysRole sysRole = sysRoleMapper.selectOne(Wrappers.<SysRole>lambdaQuery().eq(SysRole::getRoleCode, roleCode));
        if (ObjectUtil.isEmpty(sysRole)) {
            sysRole = new SysRole();
            sysRole.setRoleName("默认角色");
            sysRole.setRoleDesc("默认角色");
            sysRole.setRoleCode(roleCode);
            sysRole.setLevel((short) 1);
            sysRole.setCreateTime(new Date());
            sysRole.setUpdateTime(new Date());
            sysRoleMapper.insert(sysRole);
        }

        JSONObject departmentUser = dingHelper.getDepartmentUserList(deptId, 0);
        JSONObject result = departmentUser.getJSONObject("result");
        boolean flag;
        while (true) {
            flag = result.getBool("has_more");
            Long nextCursor = result.getLong("next_cursor");
            JSONArray list = result.getJSONArray("list");
            for (JSONObject entries : JSONUtil.toList(list, JSONObject.class)) {
                log.info("用户信息：" + entries.toString());
                String jobNumber = entries.getStr("job_number");
                String userid = entries.getStr("userid");
                String name = entries.getStr("name");

                log.info("工号：" + entries.getStr("job_number")); // 工号
                log.info("用户id：" + entries.getStr("userid")); // ding_talk_uid
                log.info("用户名称：" + entries.getStr("name")); // 姓名
                SysUser sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDingTalkUid, userid).last("limit 1"));
                if (sysUser == null) {
                    sysUser = new SysUser();
                    sysUser.setDingTalkUid(userid);
                    if (StringUtils.isBlank(jobNumber)) {
                        sysUser.setLoginName("未知工号_" + name);
                    } else {
                        sysUser.setLoginName(jobNumber + "_" + name);
                    }
                    sysUser.setName(name);
                    sysUser.setAvatarUrl(entries.getStr("avatar"));
                    sysUser.setPassword(bCryptEncode.encode(configService.getValueByKey("GLOBAL_DEFAULT_PWD")));
                    sysUserMapper.insert(sysUser);
                    sysUser = sysUserMapper.selectOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDingTalkUid, userid).last("limit 1"));
                    JSONArray deptIdList = entries.getJSONArray("dept_id_list");
                    for (String userDeptId : JSONUtil.toList(deptIdList, String.class)) {
                        Org orgByRefOid = orgService.getOne(Wrappers.<Org>lambdaQuery().eq(Org::getRefOid, userDeptId));
                        UserOrgRole userOrgRole = new UserOrgRole();
                        userOrgRole.setRoleId(sysRole.getId());
                        userOrgRole.setRoleCode(sysRole.getRoleCode());
                        userOrgRole.setUid(sysUser.getId());
                        userOrgRole.setOid(orgByRefOid.getOid());
                        userOrgRole.setFlagEnabled((short)1);
                        UserOrgRole userOrgRole1 = userOrgRoleMapper.selectOne(Wrappers.<UserOrgRole>lambdaQuery().eq(UserOrgRole::getUid, userOrgRole.getUid())
                                .eq(UserOrgRole::getOid, userOrgRole.getOid()).eq(UserOrgRole::getRoleId, userOrgRole.getRoleId()));
                        if (userOrgRole1 == null) {
                            userOrgRoleMapper.insert(userOrgRole);
                        }
                    }
                } else {
                    // 更新用户信息，删除组织角色关系
                    sysUser.setDingTalkUid(userid);
                    sysUser.setName(name);
                    sysUser.setAvatarUrl(entries.getStr("avatar"));
                    sysUserMapper.updateById(sysUser);
                }
            }
            if (!flag) {
                break;
            }
            departmentUser = dingHelper.getDepartmentUserList(deptId, nextCursor);
            result = departmentUser.getJSONObject("result");
        }
    }

    private void syncDept(long parentDeptId, int level) throws Exception {
        Org parentOrg = orgService.getOne(Wrappers.<Org>lambdaQuery().eq(Org::getRefOid, parentDeptId + ""));
        JSONObject departmentList = dingHelper.getDepartmentList(parentDeptId);
        JSONArray result = departmentList.getJSONArray("result");
        for (int i = 0; i < result.size(); i++) {
            JSONObject jsonObject = result.getJSONObject(i);
            // 添加或更新组织信息
            log.info("部门名称：" + jsonObject.getStr("name"));
            log.info("部门id：" + jsonObject.getLong("dept_id"));
            log.info("部门级别：" + level);
            String departmentName = jsonObject.getStr("name");
            Long deptId = jsonObject.getLong("dept_id");
            Org org = orgService.getOne(Wrappers.<Org>lambdaQuery().eq(Org::getRefOid, deptId + ""));
            if (org == null) {
                org = new Org();
                org.setName(departmentName);
                org.setFullname(departmentName);
                org.setType(1);
                org.setRefOid(deptId + "");
                org.setLevel((short) level);
                org.setPoid(parentOrg.getOid());
                // 根据组织属性表中数据以及组织级别添加的对应id
                org.setOrgPropertyId(orgPropertyMapper.selectOne(Wrappers.<OrgProperty>lambdaQuery()
                        .eq(OrgProperty::getLevel, level).orderByDesc(OrgProperty::getId).last("limit 1")).getId());
                orgService.addOrg(org);
                log.info(org.toString());
            } else {
                org.setName(departmentName);
                org.setFullname(departmentName);
                org.setType(1);
                org.setRefOid(deptId + "");
                org.setLevel((short) level);
                org.setPoid(parentOrg.getOid());
                org.setOrgPropertyId(level + 14);
                orgService.updateOrg(org);
            }
            // 递归查询下级部门
            syncDept(deptId, level + 1);
        }
    }
}
