package com.malk.service.aliwork.impl;

import com.alibaba.fastjson.JSON;
import com.malk.server.common.McException;
import com.malk.server.aliwork.YDAuth;
import com.malk.server.dingtalk.DDR_New;
import com.malk.service.aliwork.YDClient_Form;
import com.malk.service.dingtalk.DDClient;
import com.malk.utils.UtilHttp;
import com.malk.utils.UtilRespMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

import static com.malk.service.aliwork.impl.YDHelpers.assertResult;
import static com.malk.service.aliwork.impl.YDHelpers.body;
import static com.malk.service.aliwork.impl.YDHelpers.mergeExt;
import static com.malk.service.aliwork.impl.YDHelpers.normPage;
import static com.malk.service.aliwork.impl.YDHelpers.normPageSize;
import static com.malk.service.aliwork.impl.YDHelpers.normSearchField;
import static com.malk.service.aliwork.impl.YDHelpers.url;
import static com.malk.service.aliwork.impl.YDHelpers.urlV2;
import static com.malk.service.aliwork.impl.YDHelpers.validatePageSize;

/**
 * 宜搭表单原子接口实现
 *
 * <p>严格对齐 {@code mjava-baseline §3.4.2}：所有 body_ext 字段透传到 HTTP body，不过滤。
 * accessToken 为 null 时回退到 {@code DDClient.initTokenHeader()} 全局 token。</p>
 *
 * <p>共用 helper（url/body/mergeExt/assertResult/normXxx）见 {@link YDHelpers}；
 * 响应类型守卫见 {@link UtilRespMapper}。</p>
 */
@Slf4j
@Service
public class YDClient_FormImpl implements YDClient_Form {

    @Autowired
    private DDClient ddClient;

    /**
     * 构造请求头：accessToken 为 null 时回退到全局 DDClient（依赖注入，留在 impl 内）。
     */
    private Map<String, String> header(YDAuth auth) {
        if (auth.getAccessToken() != null && !auth.getAccessToken().isEmpty()) {
            Map<String, String> h = new HashMap<>();
            h.put("x-acs-dingtalk-access-token", auth.getAccessToken());
            return h;
        }
        return ddClient.initTokenHeader();
    }

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

    @Override
    public String saveForm(YDAuth auth, String formUuid, String formDataJson, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formUuid", formUuid);
        body.put("formDataJson", formDataJson);
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(DDR_New.doPost(url("/forms/instances"), header(auth), null, body), "saveForm");
        return UtilRespMapper.asString(r.getResult());
    }

    @Override
    public Map<String, Object> updateForm(YDAuth auth, String formInstanceId, String updateFormDataJson, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formInstanceId", formInstanceId);
        body.put("updateFormDataJson", updateFormDataJson);
        body = mergeExt(body, body_ext);
        String response = UtilHttp.doPut(url("/forms/instances"), header(auth), null, body);
        return mapResponse(response, "updateForm");
    }

    @Override
    public Map<String, Object> upsertForm(YDAuth auth, String formUuid, String searchFieldJson, String formDataJson, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formUuid", formUuid);
        body.put("searchFieldJson", searchFieldJson);
        body.put("formDataJson", formDataJson);
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(DDR_New.doPost(urlV2("/forms/instances/insertOrUpdate"), header(auth), null, body), "upsertForm");
        return UtilRespMapper.asMap(r.getResult());
    }

    @Override
    public Boolean deleteForm(YDAuth auth, String formInstanceId, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formInstanceId", formInstanceId);
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult((DDR_New) UtilHttp.doDelete(url("/forms/instances"), header(auth), body, DDR_New.class), "deleteForm");
        return UtilRespMapper.asBool(r.getResult());
    }

    @Override
    public Integer deleteFormByCondition(YDAuth auth, String formUuid, String searchFieldJson, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formUuid", formUuid);
        body.put("searchFieldJson", searchFieldJson);
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(DDR_New.doPost(url("/forms/instances/batchRemove"), header(auth), null, body), "deleteFormByCondition");
        return UtilRespMapper.asInt(r.getResult(), 0);
    }

    @Override
    public Map<String, Object> updateFormComponents(YDAuth auth, List<String> formInstanceIdList, String updateFormDataJson, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formInstanceIdList", formInstanceIdList);
        body.put("updateFormDataJson", updateFormDataJson);
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult((DDR_New) UtilHttp.doPut(url("/forms/instances/components"), header(auth), body, DDR_New.class), "updateFormComponents");
        return UtilRespMapper.asMap(r.getResult());
    }

    @Override
    public List<String> batchSaveForm(YDAuth auth, String formUuid, String formDataListJson, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formUuid", formUuid);
        body.put("formDataListJson", formDataListJson);
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(DDR_New.doPost(url("/forms/instances/batchSave"), header(auth), null, body), "batchSaveForm");
        return UtilRespMapper.asStringList(r.getResult());
    }

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

    @Override
    public Map<String, Object> getForm(YDAuth auth, String formInstanceId, Map<String, Object> body_ext) {
        Map<String, Object> param = mergeExt(body(auth), body_ext);
        String response = UtilHttp.doGet(url("/forms/instances/" + formInstanceId),
                header(auth), param);
        return mapResponse(response, "getForm");
    }

    @SuppressWarnings("unchecked")
    private Map<String, Object> mapResponse(String response, String action) {
        if (response == null || response.trim().isEmpty()) {
            throw new McException("YIDA_NULL_RESPONSE", "宜搭接口 [" + action + "] 返回空");
        }
        Map<String, Object> payload = JSON.parseObject(response, Map.class);
        if (payload == null) {
            throw new McException("YIDA_INVALID_RESPONSE", "宜搭接口 [" + action + "] 响应格式错误");
        }
        if (Boolean.FALSE.equals(payload.get("success")) || isErrorPayload(payload)) {
            String code = String.valueOf(payload.get("code"));
            String message = String.valueOf(payload.get("message"));
            throw new McException("null".equals(code) ? "YIDA_ERROR" : code,
                    "宜搭接口 [" + action + "] 失败: " + message);
        }
        Object result = payload.get("result");
        if (result instanceof Map) {
            return (Map<String, Object>) result;
        }
        if (result instanceof String && String.valueOf(result).trim().startsWith("{")) {
            return JSON.parseObject(String.valueOf(result), Map.class);
        }
        return payload;
    }

    private boolean isErrorPayload(Map<String, Object> payload) {
        return payload.containsKey("code") && !payload.containsKey("formData")
                && !payload.containsKey("formInstId") && !payload.containsKey("result");
    }

    @Override
    public Map<String, Object> searchForm(YDAuth auth, String formUuid, String searchFieldJson,
                                          Integer currentPage, Integer pageSize, Map<String, Object> body_ext) {
        validatePageSize(pageSize);
        Map<String, Object> body = body(auth);
        body.put("formUuid", formUuid);
        body.put("searchFieldJson", normSearchField(searchFieldJson));
        body.put("currentPage", normPage(currentPage));
        body.put("pageSize", normPageSize(pageSize));
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(DDR_New.doPost(url("/forms/instances/search"), header(auth), null, body), "searchForm");
        return UtilRespMapper.asMap(r.getResult());
    }

    @Override
    public List<String> listFormIds(YDAuth auth, String formUuid, String searchFieldJson,
                                    Integer currentPage, Integer pageSize, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("searchFieldJson", normSearchField(searchFieldJson));
        body.put("currentPage", normPage(currentPage));
        body.put("pageSize", normPageSize(pageSize));
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(
                DDR_New.doPost(url("/forms/instances/ids/" + auth.getAppType() + "/" + formUuid), header(auth), null, body),
                "listFormIds"
        );
        return UtilRespMapper.asStringList(r.getResult());
    }

    @Override
    public Map<String, Object> listFormsAll(YDAuth auth, String formUuid, String searchFieldJson,
                                            Integer currentPage, Integer pageSize, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formUuid", formUuid);
        body.put("searchFieldJson", normSearchField(searchFieldJson));
        body.put("currentPage", normPage(currentPage));
        body.put("pageSize", normPageSize(pageSize));
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(DDR_New.doPost(url("/forms/instances/advances/queryAll"), header(auth), null, body), "listFormsAll");
        return UtilRespMapper.asMap(r.getResult());
    }

    @Override
    public List<Map<String, Object>> listInnerTable(YDAuth auth, String formInstanceId, Map<String, Object> body_ext) {
        Map<String, Object> param = mergeExt(body(auth), body_ext);
        DDR_New r = assertResult(
                DDR_New.doGet(url("/forms/innerTables/" + formInstanceId), header(auth), param),
                "listInnerTable"
        );
        return UtilRespMapper.asMapList(r.getResult());
    }

    @Override
    public List<Map<String, Object>> listFormOperations(YDAuth auth, String formInstanceId, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formInstanceId", formInstanceId);
        body = mergeExt(body, body_ext);
        DDR_New r = assertResult(DDR_New.doPost(url("/forms/operationsLogs/query"), header(auth), null, body), "listFormOperations");
        return UtilRespMapper.asMapList(r.getResult());
    }

    @Override
    public List<Map<String, Object>> listForms(YDAuth auth, Map<String, Object> body_ext) {
        Map<String, Object> param = mergeExt(body(auth), body_ext);
        DDR_New r = assertResult(DDR_New.doGet(url("/forms"), header(auth), param), "listForms");
        return UtilRespMapper.asMapList(r.getResult());
    }

    @Override
    public void remarkForm(YDAuth auth, String formInstanceId, String remark, Map<String, Object> body_ext) {
        Map<String, Object> body = body(auth);
        body.put("formInstanceId", formInstanceId);
        body.put("remark", remark);
        body = mergeExt(body, body_ext);
        assertResult(DDR_New.doPost(url("/forms/remarks"), header(auth), null, body), "remarkForm");
    }

    // ================================================================
    //  附件临时免登
    // ================================================================

    @Override
    public String convertTempUrl(YDAuth auth, String fileUrl, Integer timeoutMs) {
        Map<String, Object> param = new HashMap<>();
        param.put("systemToken", auth.getSystemToken());
        param.put("userId", auth.resolvedUserId());
        param.put("fileUrl", fileUrl);
        param.put("timeout", timeoutMs == null ? 60_000 : timeoutMs);
        DDR_New r = assertResult(
                DDR_New.doGet(url("/apps/temporaryUrls/" + auth.getAppType()), header(auth), param),
                "convertTempUrl"
        );
        return UtilRespMapper.asString(r.getResult());
    }
}
