package com.malk.service.aliwork;

import com.malk.server.aliwork.YDAuth;

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

/**
 * 宜搭表单原子接口（Client 层）
 *
 * <p>与宜搭开放平台表单 API 1:1 对齐，遵守 {@code mjava-baseline §3.4.2}：</p>
 * <ul>
 *   <li>第 1 参固定 {@link YDAuth}（封装 accessToken + appType + systemToken + userId）</li>
 *   <li>必填参数按官方文档顺序显式声明</li>
 *   <li>可选参数全部放入 {@code body_ext}，允许为 null；所有已知 key 在各方法 javadoc 中枚举</li>
 *   <li>返回原始 response 或 {@code Map} / {@code List<Map>}（不做业务加工）</li>
 * </ul>
 *
 * <p>与旧版 {@link YDClient#operateData} / {@link YDClient#queryData} 聚合式接口**并存**；
 * 新业务优先调用本接口，旧代码按节奏迁移。</p>
 *
 * @apiNote 官方文档总入口 https://open.dingtalk.com/document/orgapp/yida-overview
 */
public interface YDClient_Form {

    // ================================================================
    //  表单实例 CRUD
    // ================================================================

    /**
     * 新增表单实例
     *
     * @apiNote POST /v1.0/yida/forms/instances
     *          https://open.dingtalk.com/document/orgapp/add-or-update-form-instances
     *
     * @param auth           鉴权上下文
     * @param formUuid       表单唯一标识（必填）
     * @param formDataJson   表单数据 JSON 字符串，key 为 fieldId（必填）
     * @param body_ext 可选参数（透传宜搭接口，不传可为 null）:
     *   - noExecuteExpression (Boolean): 是否跳过公式字段计算，默认 false
     *   - language (String): zh_CN / en_US
     *   - appType / systemToken / userId: 本实现会优先使用 auth 中的值覆盖
     * @return 新增成功的 formInstanceId
     */
    String saveForm(YDAuth auth, String formUuid, String formDataJson, Map<String, Object> body_ext);

    /**
     * 更新表单实例
     *
     * @apiNote PUT /v1.0/yida/forms/instances
     *          https://open.dingtalk.com/document/orgapp/update-form-data
     *
     * @param auth                 鉴权上下文
     * @param formInstanceId       表单实例 ID（必填）
     * @param updateFormDataJson   需更新的字段 JSON（必填）
     * @param body_ext 可选参数:
     *   - useLatestVersion (Boolean): 默认 false，true=覆盖最新版本不做乐观锁检查（后台批量同步建议 true）
     *   - ignoreEmpty (Boolean): 默认 true，false=不忽略空值（日期字段需要设 false 才会正确写入）
     *   - noExecuteExpression (Boolean)
     * @return 被更新字段的 Map
     */
    Map<String, Object> updateForm(YDAuth auth, String formInstanceId, String updateFormDataJson, Map<String, Object> body_ext);

    /**
     * upsert 表单（不存在则新增，存在则更新）
     *
     * @apiNote POST /v2.0/yida/forms/instances/insertOrUpdate（v2 更准确的 searchCondition 匹配）
     *          https://open.dingtalk.com/document/orgapp/update-or-save-form-data-v2
     *
     * @param auth                 鉴权上下文
     * @param formUuid             表单唯一标识（必填）
     * @param searchFieldJson      匹配条件 JSON（必填）；日期字段必须用字符串数组格式避免 selectListException
     * @param formDataJson         表单数据 JSON（必填）
     * @param body_ext 可选参数:
     *   - useLatestVersion (Boolean)
     *   - ignoreEmpty (Boolean)
     *   - noExecuteExpression (Boolean)
     * @return upsert 结果（含 formInstanceId 与操作类型 create/update）
     */
    Map<String, Object> upsertForm(YDAuth auth, String formUuid, String searchFieldJson, String formDataJson, Map<String, Object> body_ext);

    /**
     * 删除表单实例
     *
     * @apiNote DELETE /v1.0/yida/forms/instances
     *          https://open.dingtalk.com/document/orgapp/delete-form-data
     *
     * @param auth              鉴权上下文
     * @param formInstanceId    表单实例 ID（必填）
     * @param body_ext          可选参数（留空）
     * @return 是否删除成功
     */
    Boolean deleteForm(YDAuth auth, String formInstanceId, Map<String, Object> body_ext);

    /**
     * 按条件批量删除表单实例
     *
     * @apiNote POST /v1.0/yida/forms/instances/batchRemove
     *          https://open.dingtalk.com/document/orgapp/delete-form-data-according-to-conditions
     *
     * @param auth              鉴权上下文
     * @param formUuid          表单 UUID（必填）
     * @param searchFieldJson   搜索条件 JSON（必填）
     * @param body_ext          可选参数
     * @return 被删除条数
     */
    Integer deleteFormByCondition(YDAuth auth, String formUuid, String searchFieldJson, Map<String, Object> body_ext);

    /**
     * 批量更新表单实例字段（同一批实例的相同字段赋值）
     *
     * @apiNote PUT /v1.0/yida/forms/instances/components
     *          https://open.dingtalk.com/document/orgapp/update-form-data-batch
     *
     * @param auth                  鉴权上下文
     * @param formInstanceIdList    实例 ID 列表（必填）
     * @param updateFormDataJson    批量更新字段 JSON（必填）
     * @param body_ext 可选参数
     */
    Map<String, Object> updateFormComponents(YDAuth auth, List<String> formInstanceIdList, String updateFormDataJson, Map<String, Object> body_ext);

    /**
     * 批量新增表单实例
     *
     * @apiNote POST /v1.0/yida/forms/instances/batchSave
     *          https://open.dingtalk.com/document/orgapp/batch-save-form-data
     *
     * @param auth              鉴权上下文
     * @param formUuid          表单 UUID（必填）
     * @param formDataListJson  表单数据列表 JSON（必填；宜搭限每批 ≤ 100）
     * @param body_ext 可选参数
     * @return 新增实例 ID 列表
     */
    List<String> batchSaveForm(YDAuth auth, String formUuid, String formDataListJson, Map<String, Object> body_ext);

    // ================================================================
    //  表单实例查询
    // ================================================================

    /**
     * 查询表单实例详情
     *
     * @apiNote GET /v1.0/yida/forms/instances/{id}
     *          https://open.dingtalk.com/document/orgapp/query-form-data
     *
     * @param auth              鉴权上下文
     * @param formInstanceId    实例 ID（必填）
     * @param body_ext 可选参数
     * @return 实例 Map（含 formData / createdTimeGMT / modifiedTimeGMT 等）
     */
    Map<String, Object> getForm(YDAuth auth, String formInstanceId, Map<String, Object> body_ext);

    /**
     * 分页查询表单实例（不含子表）
     *
     * @apiNote POST /v1.0/yida/forms/instances/search
     *          https://open.dingtalk.com/document/orgapp/retrieve-search-form-information
     *
     * @param auth              鉴权上下文
     * @param formUuid          表单 UUID（必填）
     * @param searchFieldJson   搜索条件 JSON（可为 "{}"）
     * @param currentPage       当前页，1 起
     * @param pageSize          每页条数，上限 100
     * @param body_ext 可选参数:
     *   - modifiedFromTimeGMT (String): yyyy-MM-dd HH:mm:ss
     *   - modifiedToTimeGMT (String)
     *   - createFromTimeGMT (String)
     *   - createToTimeGMT (String)
     *   - originatorId (String): 发起人 userId 过滤
     *   - dynamicOrder (String): 排序字段 JSON
     *   - formDataRevision (Integer): 表单数据版本
     * @return {@code Map} 含 currentPage/totalCount/data（List<Map>）
     */
    Map<String, Object> searchForm(YDAuth auth, String formUuid, String searchFieldJson,
                                   Integer currentPage, Integer pageSize, Map<String, Object> body_ext);

    /**
     * 分页查询表单实例 ID 列表（轻量）
     *
     * @apiNote POST /v1.0/yida/forms/instances/ids/{appType}/{formUuid}
     *          https://open.dingtalk.com/document/orgapp/retrieve-the-list-of-form-ids
     *
     * @param auth              鉴权上下文
     * @param formUuid          表单 UUID
     * @param searchFieldJson   搜索条件 JSON
     * @param currentPage       当前页
     * @param pageSize          每页条数
     * @param body_ext          同 searchForm
     * @return 实例 ID 列表
     */
    List<String> listFormIds(YDAuth auth, String formUuid, String searchFieldJson,
                             Integer currentPage, Integer pageSize, Map<String, Object> body_ext);

    /**
     * 全量查询表单实例（含子表数据）
     *
     * @apiNote POST /v1.0/yida/forms/instances/advances/queryAll
     *          https://open.dingtalk.com/document/orgapp/retrieve-list-all
     *
     * @param auth              鉴权上下文
     * @param formUuid          表单 UUID（必填）
     * @param searchFieldJson   搜索条件 JSON
     * @param currentPage       当前页
     * @param pageSize          每页条数，上限 100；子表数据多时建议 {@link com.malk.server.aliwork.YDConf#PAGE_SIZE_DETAILS}
     * @param body_ext          同 searchForm
     * @return 分页 Map（含 data 为 List<Map> 且含子表）
     */
    Map<String, Object> listFormsAll(YDAuth auth, String formUuid, String searchFieldJson,
                                     Integer currentPage, Integer pageSize, Map<String, Object> body_ext);

    /**
     * 查询某表单实例的子表明细
     *
     * @apiNote GET /v1.0/yida/forms/innerTables/{formInstanceId}
     *
     * @param auth              鉴权上下文
     * @param formInstanceId    父表实例 ID
     * @param body_ext 可选:
     *   - tableFieldId (String): 指定子表组件 ID（不传则返回所有子表）
     *   - currentPage (Integer)
     *   - pageSize (Integer)
     * @return 子表数据列表
     */
    List<Map<String, Object>> listInnerTable(YDAuth auth, String formInstanceId, Map<String, Object> body_ext);

    /**
     * 查询表单操作日志（变更历史）
     *
     * @apiNote POST /v1.0/yida/forms/operationsLogs/query
     *          https://open.dingtalk.com/document/orgapp/query-form-operations-logs
     *
     * @param auth              鉴权上下文
     * @param formInstanceId    实例 ID（必填）
     * @param body_ext 可选:
     *   - pageNumber (Integer)
     *   - pageSize (Integer)
     *   - startTimeGMT / endTimeGMT (String)
     * @return 操作日志列表
     */
    List<Map<String, Object>> listFormOperations(YDAuth auth, String formInstanceId, Map<String, Object> body_ext);

    /**
     * 查询应用下表单元数据列表
     *
     * @apiNote GET /v1.0/yida/forms
     *          https://open.dingtalk.com/document/orgapp/retrieve-the-forms-list-of-an-application
     *
     * @param auth              鉴权上下文
     * @param body_ext 可选:
     *   - currentPage (Integer)
     *   - pageSize (Integer)
     *   - formType (String): RECEIPT_FORM / PROCESS_FORM
     * @return 表单元数据列表
     */
    List<Map<String, Object>> listForms(YDAuth auth, Map<String, Object> body_ext);

    /**
     * 添加表单评论
     *
     * @apiNote POST /v1.0/yida/forms/remarks
     *
     * @param auth              鉴权上下文
     * @param formInstanceId    实例 ID（必填）
     * @param remark            评论内容（必填）
     * @param body_ext 可选:
     *   - atUserIds (List<String>): @ 的用户 userId 列表
     *   - attachments (List<Map>): 附件列表
     */
    void remarkForm(YDAuth auth, String formInstanceId, String remark, Map<String, Object> body_ext);

    // ================================================================
    //  附件临时免登 URL（从旧 YDClient 迁入原子接口形态）
    // ================================================================

    /**
     * 获取附件临时免登 URL
     *
     * @apiNote GET /v1.0/yida/apps/temporaryUrls/{appType}
     *
     * @param auth              鉴权上下文
     * @param fileUrl           原始附件 URL（必填）
     * @param timeoutMs         有效期毫秒，默认 60_000，最大 24 * 3600 * 1000
     * @return 带签名的临时可访问 URL
     */
    String convertTempUrl(YDAuth auth, String fileUrl, Integer timeoutMs);
}
