package com.gzzm.lobster.pending;

import com.gzzm.lobster.artifact.Artifact;
import com.gzzm.lobster.artifact.ArtifactService;
import com.gzzm.lobster.common.PendingRequestType;
import com.gzzm.lobster.identity.UserContext;
import com.gzzm.lobster.oa.OaFileClient;
import com.gzzm.platform.commons.Tools;
import net.cyan.arachne.annotation.Service;
import net.cyan.nest.annotation.Inject;

import java.util.Map;

/**
 * Executes the backend side of confirmed pending actions.
 */
@Service
public class PendingActionResolver {

    @Inject private ArtifactService artifactService;
    @Inject private OaFileClient oaFileClient;

    public String executeIfApplicable(PendingRequest p, UserContext user, String action,
                                      Map<String, Object> responsePayload) {
        ActionResult result = executeWithResultIfApplicable(p, user, action, responsePayload);
        return result == null ? null : result.getMessage();
    }

    public ActionResult executeWithResultIfApplicable(PendingRequest p, UserContext user, String action,
                                                     Map<String, Object> responsePayload) {
        if (p == null || p.getType() != PendingRequestType.confirm_action) return null;
        if (!"CONFIRM".equalsIgnoreCase(action)) return null;

        Map<String, Object> payload = parsePayload(p.getPayloadJson());
        if (payload == null) return null;
        String saveMode = str(payload.get("saveMode"));
        if (saveMode == null) return null;
        String artifactId = str(payload.get("artifactId"));
        String sourceOaFileId = str(payload.get("sourceOaFileId"));
        boolean binary = Boolean.TRUE.equals(payload.get("binary"));

        boolean externalWriteAttempted = false;
        try {
            if ("OVERWRITE_ORIGINAL".equalsIgnoreCase(saveMode)) {
                if (artifactId == null || sourceOaFileId == null) {
                    return ActionResult.noSideEffect("[OA 覆盖失败] 缺少 artifactId 或 sourceOaFileId");
                }
                Artifact a = artifactService.get(artifactId);
                if (a == null) {
                    return ActionResult.noSideEffect("[OA 覆盖失败] artifact 不存在: " + artifactId);
                }
                if (!a.getUserId().equals(user.getUserId())) {
                    return ActionResult.noSideEffect("[OA 覆盖失败] artifact 归属校验未通过");
                }
                if (binary) {
                    byte[] bytes = artifactService.readArtifactBytes(artifactId);
                    externalWriteAttempted = true;
                    oaFileClient.overwriteBytes(user, sourceOaFileId,
                            bytes == null ? new byte[0] : bytes);
                } else {
                    String content = artifactService.readArtifactContent(artifactId, 0, 0);
                    externalWriteAttempted = true;
                    oaFileClient.overwrite(user, sourceOaFileId, content == null ? "" : content);
                }
                return ActionResult.sideEffectApplied("[已覆盖 OA 文件] fileId="
                        + sourceOaFileId + "，工件=" + a.getTitle());
            }
            if ("SUBMIT_FOR_APPROVAL".equalsIgnoreCase(saveMode)) {
                return ActionResult.noSideEffect("[SUBMIT_FOR_APPROVAL 未支持] 当前环境未接入 OA 审批流，artifact="
                        + artifactId + " 没有执行任何 OA 写动作；请改用 save_to_oa saveMode=NEW_FILE 或由用户手工走审批。");
            }
        } catch (Throwable t) {
            try { Tools.log("[PendingActionResolver] execute failed", t); } catch (Throwable ignore) { /* ignore */ }
            String message = "[OA 动作执行失败] "
                    + (t.getMessage() == null ? t.getClass().getSimpleName() : t.getMessage());
            return externalWriteAttempted
                    ? ActionResult.sideEffectApplied(message)
                    : ActionResult.noSideEffect(message);
        }
        return null;
    }

    public static final class ActionResult {
        private final String message;
        private final boolean sideEffectApplied;

        private ActionResult(String message, boolean sideEffectApplied) {
            this.message = message;
            this.sideEffectApplied = sideEffectApplied;
        }

        public static ActionResult noSideEffect(String message) {
            return new ActionResult(message, false);
        }

        public static ActionResult sideEffectApplied(String message) {
            return new ActionResult(message, true);
        }

        public String getMessage() { return message; }
        public boolean isSideEffectApplied() { return sideEffectApplied; }
    }

    private static Map<String, Object> parsePayload(String json) {
        if (json == null || json.isEmpty()) return null;
        try {
            return com.gzzm.lobster.common.JsonUtil.fromJsonToMap(json);
        } catch (Throwable t) {
            return null;
        }
    }

    private static String str(Object o) { return o == null ? null : String.valueOf(o); }
}
