package com.usoftchina.dingtalk.sdk;

import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.*;
import com.dingtalk.api.response.*;
import com.usoftchina.dingtalk.sdk.config.DingTalkProperties;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 通讯录
 *
 * @author yingp
 * @date 2020/2/19
 */
public class AddrBookSdk extends BaseSdk {

    public AddrBookSdk(DingTalkProperties properties) {
        super(properties);
    }

    /**
     * 获取用户userid
     *
     * @param agentCode 应用code
     * @param authCode  免登授权码
     * @return
     */
    public OapiUserGetuserinfoResponse getUserInfo(String agentCode, String authCode) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getuserinfo");
        OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
        request.setCode(authCode);
        request.setHttpMethod("GET");
        OapiUserGetuserinfoResponse resp = cached(() -> client.execute(request, getAccessToken(agentCode)));
        assertOK(resp);
        return resp;
    }

    /**
     * 获取用户详情
     *
     * @param agentCode 应用code
     * @param userId    员工id
     * @return
     */
    public OapiUserGetResponse getUser(String agentCode, String userId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get");
        OapiUserGetRequest req = new OapiUserGetRequest();
        req.setUserid(userId);
        req.setHttpMethod("GET");
        OapiUserGetResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp;
    }

    /**
     * 新增成员
     *
     * @param agentCode 应用code
     * @param req
     */
    public String createUser(String agentCode, OapiUserCreateRequest req) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/create");
        OapiUserCreateResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getUserid();
    }

    /**
     * 更新成员
     *
     * @param agentCode 应用code
     * @param req
     */
    public void updateUser(String agentCode, OapiUserUpdateRequest req) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/update");
        OapiUserUpdateResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
    }

    /**
     * 删除成员
     *
     * @param agentCode 应用code
     * @param userId    人员ID
     */
    public void deleteUser(String agentCode, String userId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/delete");
        OapiUserDeleteRequest req = new OapiUserDeleteRequest();
        req.setUserid(userId);
        req.setHttpMethod("GET");
        OapiUserDeleteResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
    }

    /**
     * 获取部门用户userid列表
     *
     * @param agentCode    应用code
     * @param departmentId 部门ID
     * @return
     */
    public List<String> getUserIdList(String agentCode, long departmentId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/getDeptMember");
        OapiUserGetDeptMemberRequest req = new OapiUserGetDeptMemberRequest();
        req.setDeptId(String.valueOf(departmentId));
        req.setHttpMethod("GET");
        OapiUserGetDeptMemberResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getUserIds();
    }

    /**
     * 获取部门用户
     *
     * @param agentCode    应用code
     * @param departmentId 部门ID
     * @return
     */
    public List<OapiUserSimplelistResponse.Userlist> getSimpleUserList(String agentCode, long departmentId) {
        List<OapiUserSimplelistResponse.Userlist> userList = new ArrayList<>();
        long size = 100;
        long offset = 0;
        while (true) {
            List<OapiUserSimplelistResponse.Userlist> tempList = getSimpleUserList(agentCode, departmentId, offset++, size);
            if (null != tempList) {
                userList.addAll(tempList);
                if (tempList.size() < size) {
                    break;
                }
            } else {
                break;
            }
        }
        return userList;
    }

    /**
     * 获取部门用户
     *
     * @param agentCode
     * @param departmentId
     * @param offset       支持分页查询，与size参数同时设置时才生效，此参数代表偏移量,偏移量从0开始
     * @param size
     * @return
     */
    private List<OapiUserSimplelistResponse.Userlist> getSimpleUserList(String agentCode, long departmentId, long offset, long size) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/simplelist");
        OapiUserSimplelistRequest req = new OapiUserSimplelistRequest();
        req.setDepartmentId(departmentId);
        req.setOffset(offset);
        req.setSize(size);
        req.setHttpMethod("GET");
        OapiUserSimplelistResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getUserlist();
    }

    /**
     * 获取部门用户详情
     *
     * @param agentCode    应用code
     * @param departmentId 部门ID
     * @param fetchChild 包含下级部门的
     * @return
     */
    public List<OapiUserListbypageResponse.Userlist> getUserList(String agentCode, long departmentId, boolean fetchChild) {
        List<OapiUserListbypageResponse.Userlist> userList = new ArrayList<>();
        long size = 100;
        int offset = 0;
        while (true) {
            List<OapiUserListbypageResponse.Userlist> tempList = getUserList(agentCode, departmentId, offset++ * size, size);
            if (null != tempList) {
                userList.addAll(tempList);
                if (tempList.size() < size) {
                    break;
                }
            } else {
                break;
            }
        }
        if (fetchChild) {
            List<Long> subList = getSubDepartmentIdList(agentCode, departmentId);
            if (!CollectionUtils.isEmpty(subList)) {
                for (Long subId : subList) {
                    userList.addAll(getUserList(agentCode, subId, fetchChild));
                }
            }
        }
        return userList;
    }

    /**
     * 获取部门用户详情
     *
     * @param agentCode
     * @param departmentId
     * @param offset       支持分页查询，与size参数同时设置时才生效，此参数代表偏移量
     * @param size
     * @return
     */
    private List<OapiUserListbypageResponse.Userlist> getUserList(String agentCode, long departmentId, long offset, long size) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/listbypage");
        OapiUserListbypageRequest req = new OapiUserListbypageRequest();
        req.setDepartmentId(departmentId);
        req.setOffset(offset);
        req.setSize(size);
        req.setHttpMethod("GET");
        OapiUserListbypageResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getUserlist();
    }

    /**
     * 根据手机号获取userid
     *
     * @param agentCode 应用code
     * @param mobile    手机号
     * @return
     */
    public String getUserIdByMobile(String agentCode, String mobile) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/user/get_by_mobile");
        OapiUserGetByMobileRequest req = new OapiUserGetByMobileRequest();
        req.setMobile(mobile);
        OapiUserGetByMobileResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getUserid();
    }

    /**
     * 创建部门
     *
     * @param agentCode 应用code
     * @param req
     * @return 部门ID
     */
    public Long createDepartment(String agentCode, OapiDepartmentCreateRequest req) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/create");
        OapiDepartmentCreateResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getId();
    }

    /**
     * 更新部门
     *
     * @param agentCode 应用code
     * @param req
     * @return
     */
    public void updateDepartment(String agentCode, OapiDepartmentUpdateRequest req) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/update");
        OapiDepartmentUpdateResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
    }

    /**
     * 删除部门
     *
     * @param agentCode    应用code
     * @param departmentId 部门ID
     */
    public void deleteDepartment(String agentCode, long departmentId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/delete");
        OapiDepartmentDeleteRequest req = new OapiDepartmentDeleteRequest();
        req.setId(String.valueOf(departmentId));
        req.setHttpMethod("GET");
        OapiDepartmentDeleteResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
    }

    /**
     * 获取子部门ID列表
     *
     * @param agentCode    应用code
     * @param departmentId 父部门ID
     * @return
     */
    public List<Long> getSubDepartmentIdList(String agentCode, long departmentId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list_ids");
        OapiDepartmentListIdsRequest req = new OapiDepartmentListIdsRequest();
        req.setId(String.valueOf(departmentId));
        req.setHttpMethod("GET");
        OapiDepartmentListIdsResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getSubDeptIdList();
    }

    /**
     * 获取部门，包括下级
     *
     * @param agentCode    应用code
     * @param departmentId 父部门ID
     * @return
     */
    public List<OapiDepartmentListResponse.Department> getDepartmentList(String agentCode, long departmentId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/list");
        OapiDepartmentListRequest req = new OapiDepartmentListRequest();
        req.setId(String.valueOf(departmentId));
        req.setFetchChild(true);
        req.setHttpMethod("GET");
        OapiDepartmentListResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp.getDepartment();
    }

    /**
     * 获取全部部门
     *
     * @param agentCode 应用code
     * @return
     */
    public List<OapiDepartmentListResponse.Department> getDepartmentList(String agentCode) {
        return getDepartmentList(agentCode, 1);
    }

    /**
     * 获取部门详情
     *
     * @param agentCode    应用code
     * @param departmentId 部门ID
     * @return
     */
    public OapiDepartmentGetResponse getDepartmentDetail(String agentCode, long departmentId) {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/department/get");
        OapiDepartmentGetRequest req = new OapiDepartmentGetRequest();
        req.setId(String.valueOf(departmentId));
        req.setHttpMethod("GET");
        OapiDepartmentGetResponse resp = cached(() -> client.execute(req, getAccessToken(agentCode)));
        assertOK(resp);
        return resp;
    }
}
