package com.malk.service.dingtalk;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 钉钉通讯录管理
 *
 * @apiNote https://open.dingtalk.com/document/orgapp/contacts-overview
 */
public interface DDClient_Contacts {

    /**
     * 获取子部门ID列表 [获取企业部门下的所有直属子部门列表]
     */
    List<Long> listSubDepartmentId(String access_token, long dept_id);

    /**
     * 获取部门列表
     */
    List<Map> listSubDepartmentDetail(String access_token, long dept_id);

    /**
     * 获取全部架构内部门_全部 ID [是否包含一级部门]
     */
    List<Long> getDepartmentId_all(String access_token, boolean containsTop);

    List<Long> getDepartmentId_all(String access_token, boolean containsTop, long deptId);

    /**
     * 获取全部架构内部门_全部 detail [是否包含一级部门]
     */
    List<Map> getDepartmentDetail_all(String access_token, boolean containsTop);

    /**
     * 获取部门用户userid列表 [无需分页]
     */
    List<String> listDepartmentUserId(String access_token, long dept_id);

    /**
     * 查询用户详情
     * -
     * [入职时间 需要再在花名册添加员工可见, 接口才会返回]
     * [手机号\邮箱等, 只有应用开通通讯录邮箱等个人信息权限，才会返回该字段: 如个人邮箱 fieldEmail]
     * ppExt: 企业邮箱org_email, 若无则字段不返回; 手机号telephone无值, 但mobile会返回
     */
    Map getUserInfoById(String access_token, String userId);

    /**
     * 根据手机号查询用户 [手机号查询仅返回userid, 查询详情后返回]
     */
    Map getUserInfoByMobile(String access_token, String mobile);

    /**
     * 删除用户
     */
    boolean deleteUser(String access_token, String userId);

    /**
     * 查询离职记录列表
     *
     * @param startTime 开始时间: 格式：YYYY-MM-DDTHH:mm:ssZ（ISO 8601/RFC 3339）
     * @param extInfo   maxResults, 每页最大条目数，最大值50. nextToken 分页游标. endTime 结束时间, 默认当前时间, 查询跨度不能超过365天
     */
    List<Map<String, String>> getLeaveEmployeeRecords(String access_token, Date startTime, Map extInfo);

    /**
     * 获取指定用户的所有父部门列表
     */
    Map listParentByUser(String access_token, String userId);

    /**
     * 创建用户 [24小时只能收到一次邀请通知, 若是频繁退出再进入, 可关闭邀请确认后自动加入, 路径: 设置 - 安全中心 - 隐私开关 - 团队添加我时需要我的确认 - 关闭]
     */
    Map createUser(String access_token, String name, String mobile, List<String> dept_id_list, Map body_ext);

    /**
     * 创建部门
     */
    Map createDepartment(String access_token, String name, long parent_id, Map body_ext);

    /**
     * 获取部门详情
     */
    Map getDepartmentInfo(String access_token, long dept_id);

    /**
     * 获取员工人数
     *
     * @param only_active 是否包含未激活钉钉人数
     */
    int getUserCount(String access_token, boolean only_active);

    ////////////////////////////// 企业账号 //////////////////////////////

    /**
     * 创建钉钉自建企业账号 [邮箱为必填]
     */
    Map createUser_dingTalk(String access_token, String login_id, String init_password, String name, List<Long> dept_id_list, Map body_ext);

    /**
     * 更新企业账号用户信息
     * ppExt: 1.开启了多部门任职，只会显示多部门任职分组里边的职位信息, 原职位信息不再显示; 2.隐藏部门的职位在名片上不展示
     */
    Map updateUser_dingTalk(String access_token, String userId, List<Long> dept_id_list, Map body_ext);

    /**
     * 授权企业帐号可加入多组织
     */
    void multiOrgPermissions(String access_token, String joinCorpId, String grantDeptIdList);

    /**
     * 邀请其他组织企业账号加入
     * ppExt: 处理逻辑 1. 授权企业帐号可加入多组织, 目前接口不受专属安全控制; 2. 加入企业接口与创建一致, 无需传递登录相关信息, 被邀请方必须为企业账号
     * fixme: 核心参数 [ outer_exclusive_corpid, outer_exclusive_userid ],  组织外邀请无需单独同意, 非激活状态也拉正常加入
     * ppExt: 邀请api, 无手机号字段, 传递创建接口 exclusive_mobile 字段也生效 [备注: 昵称无效, 只对企业账号归属的组织创建有效, 邀请时会显示原组织定义]
     */
    Map inviteExclusiveUser(String access_token, String name, List<Long> dept_id_list, String outer_exclusive_corpid, String outer_exclusive_userid, Map body_ext);

    // ================================================================================
    //  v2 对齐方法（extend-dingtalk-contacts-api / capability dingtalk-contacts-v2）
    //  所有新方法严格遵守 mjava-baseline §3.4.2：必填显式 + body_ext 透传 + javadoc 枚举 + @apiNote
    //  旧方法保留不动，按 §3.4.4 并存策略，新业务优先使用 _v2 / 无后缀新方法
    // ================================================================================

    // ============================= 用户管理 User =============================

    /**
     * 创建用户（v2 对齐版，与 createUser 并存）
     *
     * @apiNote POST /topapi/v2/user/create
     *          https://open.dingtalk.com/document/orgapp/user-information-creation
     *
     * @param access_token 钉钉应用 accessToken
     * @param name         姓名（必填）
     * @param mobile       手机号（必填，企业内不重复）
     * @param dept_id_list 部门 ID 列表（必填，≥ 1）
     * @param body_ext 可选参数（透传钉钉 body，不过滤）:
     *   - userid (String): 自定义 userid，不传则自动生成
     *   - hired_date (Long): 入职时间毫秒
     *   - job_number (String): 工号
     *   - title (String): 职位
     *   - work_place (String): 办公地点
     *   - remark (String): 备注
     *   - email (String): 邮箱（需通讯录权限）
     *   - org_email (String): 企业邮箱
     *   - org_email_type (String): profession / premium
     *   - extension (String): 扩展属性 JSON
     *   - senior_mode (Boolean): 高管模式
     *   - hide_mobile (Boolean): 隐藏手机号
     *   - telephone (String): 分机号
     *   - dept_order_list (List<Map>): 部门内排序
     *   - dept_title_list (List<Map>): 部门内职位
     *   - login_email (String): 企业账号登录邮箱
     *   - exclusive_account (Boolean): 专属账号
     *   - exclusive_account_type (String): sso / custom
     *   - exclusive_mobile (String): 专属账号手机号
     *   最后同步 2026-04-19
     * @return Map 含 userid / isLeaderInDepts
     */
    Map createUser_v2(String access_token, String name, String mobile, List<String> dept_id_list, Map body_ext);

    /**
     * 更新用户（仅新增，旧无同名方法）
     *
     * @apiNote POST /topapi/v2/user/update
     *          https://open.dingtalk.com/document/orgapp/user-information-update
     *
     * @param access_token 钉钉 accessToken
     * @param userid       用户 userid（必填）
     * @param body_ext 可选参数（不传保留原值）:
     *   - name / mobile / dept_id_list / hired_date / job_number / title / work_place / remark
     *   - email / org_email / senior_mode / hide_mobile / telephone / extension
     *   - dept_order_list / dept_title_list 等全部 createUser 支持字段
     *   最后同步 2026-04-19
     * @return Map（通常为空或含刷新后字段）
     */
    Map updateUser(String access_token, String userid, Map body_ext);

    /**
     * 查询用户详情（v2 命名对齐）
     *
     * @apiNote POST /topapi/v2/user/get
     *          https://open.dingtalk.com/document/orgapp/query-user-details
     *
     * @param access_token 钉钉 accessToken
     * @param userid       用户 userid（必填）
     * @param body_ext 可选参数:
     *   - language (String): zh_CN / en_US
     */
    Map getUser_v2(String access_token, String userid, Map body_ext);

    /**
     * 根据手机号查询用户（v2 命名对齐）
     *
     * @apiNote POST /topapi/v2/user/getbymobile
     *          https://open.dingtalk.com/document/orgapp/query-users-by-phone-number
     *
     * @param access_token 钉钉 accessToken
     * @param mobile       手机号
     * @param body_ext 可选参数:
     *   - support_exclusive_account_search (Boolean): 是否支持搜索专属账号
     */
    Map getUserByMobile_v2(String access_token, String mobile, Map body_ext);

    /**
     * 查询部门用户 userid 简单列表
     *
     * @apiNote POST /topapi/user/listsimple
     *          https://open.dingtalk.com/document/orgapp/queries-basic-user-information
     *
     * @param access_token 钉钉 accessToken
     * @param dept_id      部门 ID
     * @param body_ext 可选参数:
     *   - cursor (Long): 分页游标
     *   - size (Long): 每页数量，默认 100，上限 100
     *   - order_field (String): modify_desc / modify_asc / entry_desc / entry_asc / custom
     *   - contain_access_limit (Boolean): 是否包含访问受限员工
     *   - language (String)
     */
    Map listUsersSimple(String access_token, long dept_id, Map body_ext);

    /**
     * 查询部门用户详情（分页，v2 版）
     *
     * @apiNote POST /topapi/v2/user/list
     *          https://open.dingtalk.com/document/orgapp/queries-the-complete-information-of-a-department-user
     *
     * @param access_token 钉钉 accessToken
     * @param dept_id      部门 ID
     * @param body_ext 同 listUsersSimple 的可选参数集
     */
    Map listDeptUserDetail_v2(String access_token, long dept_id, Map body_ext);

    /**
     * 查询未激活或已激活用户
     *
     * @apiNote POST /topapi/inactive/user/v2/get
     *          https://open.dingtalk.com/document/orgapp/queries-the-inactive-users-or-active-users-under-an-enterprise
     *
     * @param access_token 钉钉 accessToken
     * @param is_active    true=激活 / false=未激活
     * @param offset       偏移
     * @param size         每页大小，上限 100
     * @param body_ext 可选:
     *   - dept_ids (List<Long>): 限定部门范围
     *   - query_date (String): 查询基准日期 yyyyMMdd
     */
    Map listInactiveUsers(String access_token, boolean is_active, long offset, long size, Map body_ext);

    /**
     * 按 unionId 查询 userid
     *
     * @apiNote POST /topapi/user/getbyunionid
     *          https://open.dingtalk.com/document/orgapp/query-a-user-by-the-union-id
     *
     * @param access_token 钉钉 accessToken
     * @param union_id     union ID
     * @param body_ext     可选参数（目前无）
     * @return Map 含 userid 与 contact_type
     */
    Map getUserByUnionId(String access_token, String union_id, Map body_ext);

    /**
     * 查询管理员列表
     *
     * @apiNote POST /topapi/user/get_admin
     *          https://open.dingtalk.com/document/orgapp/query-the-administrator-list
     *
     * @param access_token 钉钉 accessToken
     * @return Map 含 admin_list（含主管理员与子管理员标记）
     */
    Map listAdmins(String access_token);

    /**
     * 查询离职员工（v2 对齐版）
     *
     * @apiNote POST /topapi/smartwork/hrm/employee/listdimission
     *          https://open.dingtalk.com/document/orgapp/dingtalk-query-the-list-of-resigned-employees
     *
     * @param access_token 钉钉 accessToken
     * @param offset       偏移
     * @param size         每页
     * @param body_ext 可选:
     *   - userid_list (List<String>): 指定 userid 过滤
     */
    Map listDimissionEmployees_v2(String access_token, long offset, long size, Map body_ext);

    // ============================= 部门管理 Department =============================

    /**
     * 创建部门（v2 对齐版）
     *
     * @apiNote POST /topapi/v2/department/create
     *          https://open.dingtalk.com/document/orgapp/address-book-creation-department-established-department
     *
     * @param access_token 钉钉 accessToken
     * @param name         部门名称
     * @param parent_id    父部门 ID
     * @param body_ext 可选:
     *   - hide_dept (Boolean): 是否隐藏
     *   - dept_permits (String): 被允许访问此部门的部门列表逗号分隔
     *   - user_permits (String): 被允许访问此部门的 userid 列表
     *   - outer_dept (Boolean): 是否外部联系人部门
     *   - outer_permit_users (String): 外部联系人查看权限 userId
     *   - outer_permit_depts (String): 外部联系人查看权限部门
     *   - create_dept_group (Boolean): 是否创建部门群
     *   - order (Long): 排序值
     *   - source_identifier (String): 外部系统同步标识
     *   最后同步 2026-04-19
     */
    Map createDepartment_v2(String access_token, String name, long parent_id, Map body_ext);

    /**
     * 更新部门
     *
     * @apiNote POST /topapi/v2/department/update
     *
     * @param access_token 钉钉 accessToken
     * @param dept_id      部门 ID
     * @param body_ext 可选字段与 createDepartment_v2 一致（name / parent_id / hide_dept / ...）
     */
    Map updateDepartment(String access_token, long dept_id, Map body_ext);

    /**
     * 删除部门
     *
     * @apiNote POST /topapi/v2/department/delete
     *
     * @param access_token 钉钉 accessToken
     * @param dept_id      部门 ID
     * @param body_ext     可选参数（通常无）
     */
    Boolean deleteDepartment(String access_token, long dept_id, Map body_ext);

    /**
     * 查询部门详情（v2 命名对齐）
     *
     * @apiNote POST /topapi/v2/department/get
     *
     * @param access_token 钉钉 accessToken
     * @param dept_id      部门 ID
     * @param body_ext 可选:
     *   - language (String)
     */
    Map getDepartment_v2(String access_token, long dept_id, Map body_ext);

    /**
     * 查询子部门详情列表（v2 命名对齐）
     *
     * @apiNote POST /topapi/v2/department/listsub
     *
     * @param access_token 钉钉 accessToken
     * @param dept_id      父部门 ID
     * @param body_ext 可选:
     *   - language (String)
     */
    List<Map> listSubDepartments_v2(String access_token, long dept_id, Map body_ext);

    /**
     * 查询部门的父部门链
     *
     * @apiNote POST /topapi/v2/department/listparentbydept
     *
     * @param access_token 钉钉 accessToken
     * @param dept_id      部门 ID
     * @param body_ext     可选参数
     * @return 父部门 ID 链 List<Long>
     */
    Map listParentByDept(String access_token, long dept_id, Map body_ext);

    // ============================= 员工字段隐藏 EmployeeField =============================

    /**
     * 新增或更新员工字段隐藏规则
     *
     * @apiNote POST /topapi/hide_field/add_or_update
     *          https://open.dingtalk.com/document/orgapp/add-or-update-the-hidden-settings-of-the-employee-property
     *
     * @param access_token 钉钉 accessToken
     * @param name         规则名称
     * @param field        字段标识
     * @param userIds      被隐藏可见范围的 userid 列表（逗号分隔）
     * @param deptIds      被隐藏可见范围的部门 ID 列表（逗号分隔）
     * @param body_ext 可选:
     *   - id (Long): 规则 ID，更新时必传
     *   - self_visible (Boolean): 本人是否可见
     *   - visible_userids (String)
     *   - visible_dept_ids (String)
     */
    Map upsertHideField(String access_token, String name, String field, String userIds, String deptIds, Map body_ext);

    /**
     * 删除员工字段隐藏规则
     *
     * @apiNote POST /topapi/hide_field/remove
     *          https://open.dingtalk.com/document/orgapp/delete-enterprise-employee-attribute-field-visibility-settings
     *
     * @param access_token 钉钉 accessToken
     * @param id           规则 ID
     */
    Boolean removeHideField(String access_token, long id);

    /**
     * 查询员工字段隐藏规则列表
     *
     * @apiNote POST /topapi/hide_field/query
     *          https://open.dingtalk.com/document/orgapp/pull-hidden-property-field-for-enterprise-employees
     *
     * @param access_token 钉钉 accessToken
     * @param size         每页
     * @param offset       偏移
     * @param body_ext     可选参数
     */
    Map listHideFields(String access_token, long size, long offset, Map body_ext);
}
