package com.kingdee.eas.custom.integration.feishu.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.JsonParser;
import com.kingdee.bos.BOSException;
import com.kingdee.eas.base.permission.UserCollection;
import com.kingdee.eas.base.permission.UserInfo;
import com.kingdee.eas.basedata.person.PersonInfo;
import com.lark.oapi.Client;
import com.lark.oapi.core.response.RawResponse;
import com.lark.oapi.core.token.AccessTokenType;
import com.lark.oapi.core.utils.Jsons;
import com.lark.oapi.service.ehr.v1.model.Employee;
import com.lark.oapi.service.ehr.v1.model.ListEmployeeReq;
import com.lark.oapi.service.ehr.v1.model.ListEmployeeResp;
import com.lark.oapi.service.ehr.v1.model.ListEmployeeRespBody;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 同步飞书用户 信息
 * @Date 2026/5/19 16:12
 * @Created by HeYuan
 */
public class SyncFeishuUserInfoUtil {
    private static Logger logger = Logger.getLogger(SyncFeishuUserInfoUtil.class);
    // 批量获取员工列表
    private static final String GET_EMPLOYEE_URL = "/open-apis/directory/v1/employees/filter?department_id_type=open_department_id&employee_id_type=open_id";


    /**
     * 通过手机号匹配,请求飞书获取用接口
     *
     * @param client
     * @param userCollection
     * @return
     * @throws Exception
     */
    public static UserCollection matchByMobile(Client client, UserCollection userCollection) throws Exception {
        UserCollection updateUserCol = new UserCollection();

        //手机号码
        Map<String, UserInfo> mobileNumberMap = new HashMap<String, UserInfo>();
        for (int i = 0; i < userCollection.size(); i++) {
            UserInfo userInfo = userCollection.get(i);
            String number = userInfo.getNumber();
            String cell = userInfo.getCell();
            if (StringUtils.isBlank(cell)) {
                logger.error("用户[" + number + "]没有维护手机号码，已忽略");
                continue;
            }
            mobileNumberMap.put(cell, userInfo);
        }

        Set<String> mobileNumbers = mobileNumberMap.keySet();

        if (mobileNumbers == null || mobileNumbers.isEmpty()) {
            throw new BOSException("获取飞书用户列表 请求参数为空!");
        }

        ArrayList<String> mobileNumberList = new ArrayList<>(mobileNumbers);

        for (int i = 0; i < mobileNumberList.size(); i += 90) {
            Set<String> values = mobileNumberList.stream()
                    .skip(i)
                    .limit(90)
                    .collect(Collectors.toSet());

            //获取请求参数
            Map<String, Object> requestParams = getRequestParamsByMobile(values);
            //请求获取飞书用户信息
            JSONArray employees = questEmployeesData(client, requestParams);

            for (int j = 0; j < employees.size(); j++) {
                JSONObject employee = employees.getJSONObject(j);
                //飞书用户id
                String employeeId = employee.getJSONObject("base_info").getString("employee_id");
                //手机号
                String mobile = employee.getJSONObject("base_info").getString("mobile");
                if (StringUtils.isNotBlank(mobile)) {
                    if (mobile.startsWith("+")) {
                        //包含了区号
                        mobile = mobile.substring(3);
                    }

                    UserInfo userInfo = mobileNumberMap.get(mobile);
                    if (userInfo != null) {
                        userInfo.put("feishuUserId", employeeId);
                        updateUserCol.add(userInfo);
                    }
                }
            }
            try {
                // 休眠1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 处理中断异常
                e.printStackTrace();
            }
        }
        return updateUserCol;
    }


    /**
     * 通过账号匹配,请求飞书获取用接口
     *
     * @param client
     * @param userCollection
     * @return
     * @throws Exception
     */
    public static UserCollection matchByUserNumber(Client client, UserCollection userCollection) throws Exception {
        //因为可能存在工号和账号不一致的情况,统一使用工号
        UserCollection updateUserCol = new UserCollection();
        //工号
        Map<String, UserInfo> userNumberMap = new HashMap<String, UserInfo>();
        for (int i = 0; i < userCollection.size(); i++) {
            UserInfo userInfo = userCollection.get(i);
            userNumberMap.put(userInfo.getNumber(), userInfo);
        }

        Set<String> userNumbers = userNumberMap.keySet();

        if (userNumbers == null || userNumbers.isEmpty()) {
            throw new BOSException("获取飞书用户列表 请求参数为空!");
        }

        ArrayList<String> userNumberList = new ArrayList<>(userNumbers);
        for (int i = 0; i < userNumberList.size(); i += 90) {
            Set<String> values = userNumberList.stream()
                    .skip(i)
                    .limit(90)
                    .collect(Collectors.toSet());
            //获取请求参数
            Map<String, Object> requestParams = getRequestParamsByJobNumber(values);
            //请求获取飞书用户信息
            JSONArray employees = questEmployeesData(client, requestParams);
            for (int j = 0; j < employees.size(); j++) {
                JSONObject employee = employees.getJSONObject(j);
                //飞书用户id
                String employeeId = employee.getJSONObject("base_info").getString("employee_id");
                //账号
                String jobNumber = employee.getJSONObject("work_info").getString("job_number");
                if (StringUtils.isNotBlank(jobNumber)) {
                    UserInfo userInfo = userNumberMap.get(jobNumber);
                    if (userInfo != null) {
                        userInfo.put("feishuUserId", employeeId);
                        updateUserCol.add(userInfo);
                    }
                }
            }
            try {
                // 休眠1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 处理中断异常
                e.printStackTrace();
            }
        }
        return updateUserCol;
    }


    /**
     * 通过工号匹配,请求飞书获取用接口
     *
     * @param client
     * @param userCollection
     * @return
     * @throws Exception
     */
    public static UserCollection matchByPersonNumber(Client client, UserCollection userCollection) throws Exception {
        //因为可能存在工号和账号不一致的情况,统一使用工号
        UserCollection updateUserCol = new UserCollection();
        //工号
        Map<String, UserInfo> jobNumberMap = new HashMap<String, UserInfo>();
        for (int i = 0; i < userCollection.size(); i++) {
            UserInfo userInfo = userCollection.get(i);
            PersonInfo person = userInfo.getPerson();
            if (person != null) {
                jobNumberMap.put(person.getNumber(), userInfo);
            } else {
                logger.error("用户[" + userInfo.getNumber() + "]没有维护对应操作人，已忽略");
            }
        }

        Set<String> jobNumbers = jobNumberMap.keySet();

        if (jobNumbers == null || jobNumbers.isEmpty()) {
            throw new BOSException("获取飞书用户列表 请求参数为空!");
        }

        ArrayList<String> jobNumberList = new ArrayList<>(jobNumbers);
        for (int i = 0; i < jobNumberList.size(); i += 90) {
            Set<String> values = jobNumberList.stream()
                    .skip(i)
                    .limit(90)
                    .collect(Collectors.toSet());
            //获取请求参数
            Map<String, Object> requestParams = getRequestParamsByJobNumber(values);
            //请求获取飞书用户信息
            JSONArray employees = questEmployeesData(client, requestParams);
            for (int j = 0; j < employees.size(); j++) {
                JSONObject employee = employees.getJSONObject(j);
                //飞书用户id
                String employeeId = employee.getJSONObject("base_info").getString("employee_id");
                //工号
                String jobNumber = employee.getJSONObject("work_info").getString("job_number");
                if (StringUtils.isNotBlank(jobNumber)) {
                    UserInfo userInfo = jobNumberMap.get(jobNumber);
                    if (userInfo != null) {
                        userInfo.put("feishuUserId", employeeId);
                        updateUserCol.add(userInfo);
                    }
                }
            }
            try {
                // 休眠1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 处理中断异常
                e.printStackTrace();
            }
        }
        return updateUserCol;
    }

    /**
     * 请求获取飞书员工信息
     *
     * @param client
     * @param requestParams
     * @return
     * @throws Exception
     */
    private static JSONArray questEmployeesData(Client client, Map<String, Object> requestParams) throws Exception {
        logger.error("请求获取飞书员工信息参数: " + JSONObject.toJSONString(requestParams));
        // 发起请求
        RawResponse resp = client.post(GET_EMPLOYEE_URL, requestParams, AccessTokenType.Tenant);
        String body = new String(resp.getBody());
        logger.info("获取飞书用户列表，请求结果： " + body);
        JSONObject result = JSONObject.parseObject(body);

        Integer code = result.getInteger("code");
        if (0 != code) {
            logger.error("获取飞书用户列表,请求失败： " + result.getString("msg"));
            throw new BOSException(result.getString("msg"));
        }
        JSONObject data = result.getJSONObject("data");
        //员工信息
        JSONArray employees = data.getJSONArray("employees");

        //分页结果
        JSONObject pageResponse = data.getJSONObject("page_response");
        //是否还有更多分页
        Boolean hasMore = pageResponse.getBoolean("has_more");

        if (hasMore) {
            //分页标记
            String pageToken = pageResponse.getString("pageToken");
            Map<String, Object> page_request = (Map<String, Object>) requestParams.get("page_request");
            page_request.put("page_token", pageToken);
            employees.addAll(questEmployeesData(client, page_request));
        }
        return employees;
    }

    /**
     * 请求获取飞书员工信息
     *
     * @param client
     * @param oldPageToken
     * @return
     * @throws Exception
     */
    private static ListEmployeeRespBody questEmployeesDataV2(Client client, String oldPageToken) throws Exception {
        // 创建请求对象
        ListEmployeeReq.Builder builder = ListEmployeeReq.newBuilder()
                .view("basic")
                .status(new Integer[]{2, 4})
                .userIdType("user_id")
                .pageSize(100);
        if (StringUtils.isNotBlank(oldPageToken)) {
            builder.pageToken(oldPageToken);
        }
        ListEmployeeReq req = builder.build();

        logger.error("请求获取飞书员工花名册信息参数: " + JSONObject.toJSONString(req));

        // 发起请求
        ListEmployeeResp resp = client.ehr().v1().employee().list(req);

        logger.info("获取飞书用户列表，请求结果： " + JSONObject.toJSONString(resp));
        // 处理服务端错误
        if (!resp.success()) {
            throw new BOSException(String.format("code:%s,msg:%s,reqId:%s, resp:%s",
                    resp.getCode(), resp.getMsg(), resp.getRequestId(), Jsons.createGSON(true, false).toJson(JsonParser.parseString(new String(resp.getRawResponse().getBody(), StandardCharsets.UTF_8)))));
        }

        Integer code = resp.getCode();
        if (0 != code) {
            logger.error("获取飞书用户列表,请求失败： " + resp.getMsg());
            throw new BOSException(resp.getMsg());
        }
        return resp.getData();
    }

    /**
     * 获取通过手机号请求参数
     *
     * @param set 匹配条件
     * @param set 匹配条件
     * @return
     * @throws BOSException
     */
    private static Map<String, Object> getRequestParamsByMobile(Set<String> set) throws BOSException {
        Map<String, Object> requestParams = new HashMap();
        //过滤条件
        Map<String, Object> filter = new HashMap<String, Object>();
        List<Map<String, Object>> conditions = new ArrayList<Map<String, Object>>();
        filter.put("conditions", conditions);
        //条件过长会导致接口调用失败,拆分参数,50条一个condition
        List<String> list = new ArrayList<String>(set);
        for (int i = 0; i < list.size(); i += 50) {
            Set<String> values = list.stream()
                    .skip(i)
                    .limit(50)
                    .collect(Collectors.toSet());

            Map<String, Object> condition = new HashMap<String, Object>();
            //根据手机号码过滤
            condition.put("field", "base_info.mobile");
            condition.put("operator", "in");
            //比较值,json字符串
            condition.put("value", "[\"" + String.join("\",\"", values) + "\"]");
            conditions.add(condition);
        }
        requestParams.put("filter", filter);

        //分页参数
        Map<String, Object> page_request = new HashMap<String, Object>();
        page_request.put("page_size", "100");//每次一百条
        page_request.put("page_token", "");
        requestParams.put("page_request", page_request);

        //需要查询的字段列表
        List<String> required_fields = new ArrayList<String>();
        required_fields.add("work_info.job_number");//工号
        required_fields.add("base_info.mobile");//手机号码
        required_fields.add("base_info.employee_id");//飞书用户id
        requestParams.put("required_fields", required_fields);
        logger.info("getRequestParamsByMobile:  " + JSONObject.toJSONString(requestParams));
        return requestParams;
    }

    /**
     * 获取工号请求参数
     *
     * @param set
     * @return
     * @throws BOSException
     */
    private static Map<String, Object> getRequestParamsByJobNumber(Set<String> set) throws BOSException {
        Map<String, Object> requestParams = new HashMap();
        //过滤条件
        Map<String, Object> filter = new HashMap<String, Object>();
        List<Map<String, Object>> conditions = new ArrayList<Map<String, Object>>();
        filter.put("conditions", conditions);

        //条件过长会导致接口调用失败,拆分参数,50条一个condition
        List<String> list = new ArrayList<String>(set);
        for (int i = 0; i < list.size(); i += 50) {
            Set<String> values = list.stream()
                    .skip(i)
                    .limit(50)
                    .collect(Collectors.toSet());

            Map<String, Object> condition = new HashMap<String, Object>();
            //根据手机号码过滤
            condition.put("field", "work_info.job_number");
            condition.put("operator", "in");
            //比较值,json字符串
            condition.put("value", "[\"" + String.join("\",\"", values) + "\"]");
            conditions.add(condition);
        }

        requestParams.put("filter", filter);

        //分页参数
        Map<String, Object> page_request = new HashMap<String, Object>();
        page_request.put("page_size", "100");//每次一百条
        page_request.put("page_token", "");
        requestParams.put("page_request", page_request);

        //需要查询的字段列表
        List<String> required_fields = new ArrayList<String>();
        required_fields.add("work_info.job_number");//工号
        required_fields.add("base_info.mobile");//手机号码
        required_fields.add("base_info.employee_id");//飞书用户id
        requestParams.put("required_fields", required_fields);
        logger.info("getRequestParamsByJobNumber:  " + JSONObject.toJSONString(requestParams));
        return requestParams;
    }

    /**
     * 通过IMD用户编码匹配飞书用户信息
     *
     * @param client
     * @param userCollection
     * @return
     * @throws Exception
     */
    public static UserCollection matchByIMDUserCode(Client client, UserCollection userCollection) throws Exception {
        //因为可能存在工号和账号不一致的情况,统一使用工号
        UserCollection updateUserCol = new UserCollection();
        //工号
        Map<String, UserInfo> iDMUserCodeMap = new HashMap<String, UserInfo>();
        for (int i = 0; i < userCollection.size(); i++) {
            UserInfo userInfo = userCollection.get(i);
            PersonInfo person = userInfo.getPerson();
            if (person != null) {
                String idmusercode = person.getString("idmusercode");
                if (StringUtils.isNotBlank(idmusercode)) {
                    iDMUserCodeMap.put(idmusercode, userInfo);
                } else {
                    logger.error("用户[" + userInfo.getNumber() + "]没有维护对应IMD用户编码，已忽略");
                }
            } else {
                logger.error("用户[" + userInfo.getNumber() + "]没有维护对应操作人，已忽略");
            }
        }

        Set<String> iDMUserCodes = iDMUserCodeMap.keySet();

        if (iDMUserCodes == null || iDMUserCodes.isEmpty()) {
            throw new BOSException("获取飞书用户列表 请求参数为空!");
        }

        Boolean hasMore = true;
        String pageToken = null;
        while (hasMore) {
            //请求获取飞书用户信息
            ListEmployeeRespBody data = questEmployeesDataV2(client, pageToken);

            logger.info("获取飞书用户列表，请求结果： " + JSONObject.toJSONString(data));

            // 业务数据处理
            Employee[] items = data.getItems();

            for (int j = 0; j < items.length; j++) {
                Employee item = items[j];
                String userId = item.getUserId();

                if (StringUtils.isNotBlank(userId)) {
                    UserInfo userInfo = iDMUserCodeMap.get(userId);
                    if (userInfo != null) {
                        userInfo.put("feishuUserId", userId);
                        updateUserCol.add(userInfo);
                    }
                }
            }

            //是否还有更多分页
            hasMore = data.getHasMore();
            //分页标记
            pageToken = data.getPageToken();
            if (StringUtils.isBlank(pageToken)) {
                break;
            }
            try {
                // 休眠1秒
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                // 处理中断异常
                e.printStackTrace();
            }
        }
        return updateUserCol;
    }
}
