package com.ruoyi.web.controller.jarvis;

import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.jarvis.domain.dto.KdocsTokenInfo;
import com.ruoyi.jarvis.service.IKdocsOAuthService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;

/**
 * 金山文档 OAuth 回调（独立路径，避免前端路由拦截）
 * 回调地址示例：https://your-domain/kdocs-callback
 */
@Anonymous
@RestController
@RequestMapping("/kdocs-callback")
public class KdocsCallbackController extends BaseController {

    private static final Logger log = LoggerFactory.getLogger(KdocsCallbackController.class);

    @Autowired
    private IKdocsOAuthService kdocsOAuthService;

    @Anonymous
    @GetMapping
    public ResponseEntity<?> oauthCallbackGet(HttpServletRequest request,
                                              @RequestParam(value = "code", required = false) String code,
                                              @RequestParam(value = "state", required = false) String state,
                                              @RequestParam(value = "error", required = false) String error,
                                              @RequestParam(value = "error_description", required = false) String errorDescription) {
        return handleOAuthCallback(request, code, state, error, errorDescription);
    }

    /**
     * 部分开放平台校验可能使用 POST；JSON body 时需回显 challenge 等字段。
     */
    @Anonymous
    @PostMapping
    public ResponseEntity<?> oauthCallbackPost(HttpServletRequest request) throws IOException {
        String ct = StringUtils.defaultString(request.getContentType()).toLowerCase();
        if (ct.contains("application/json")) {
            StringBuilder sb = new StringBuilder();
            try (BufferedReader r = request.getReader()) {
                char[] buf = new char[4096];
                int n;
                while ((n = r.read(buf)) != -1) {
                    sb.append(buf, 0, n);
                }
            }
            String raw = sb.toString();
            if (StringUtils.isNotBlank(raw)) {
                try {
                    JSONObject o = JSON.parseObject(raw);
                    if (o != null && o.containsKey("code")) {
                        Object cv = o.get("code");
                        if (cv != null) {
                            String c = String.valueOf(cv);
                            if (StringUtils.isNotBlank(c) && !"null".equals(c)) {
                                return handleOAuthCallback(request, c, o.getString("state"), o.getString("error"), o.getString("error_description"));
                            }
                        }
                    }
                } catch (Exception e) {
                    log.debug("解析 OAuth POST JSON: {}", e.getMessage());
                }
            }
            return KdocsCallbackProbeResponses.callbackReadyJson(request, raw);
        }
        String code = request.getParameter("code");
        String state = request.getParameter("state");
        String error = request.getParameter("error");
        String errorDescription = request.getParameter("error_description");
        return handleOAuthCallback(request, code, state, error, errorDescription);
    }

    private ResponseEntity<?> handleOAuthCallback(HttpServletRequest request, String code, String state, String error, String errorDescription) {
        try {
            if (error != null) {
                String msg = errorDescription != null ? errorDescription : error;
                log.error("金山文档授权失败: {}", msg);
                return htmlPage(false, "授权失败: " + msg, null);
            }
            // 无 code：多为平台校验回调可达性，或用户直接打开本地址（非授权失败）
            if (StringUtils.isBlank(code)) {
                return callbackEndpointInfoPage(request);
            }
            log.info("金山文档授权回调 code 已收到 state={}", state);
            KdocsTokenInfo tokenInfo = kdocsOAuthService.getAccessTokenByCode(code);
            if (tokenInfo.getUserId() == null) {
                return htmlPage(false, "无法解析用户标识", null);
            }
            kdocsOAuthService.saveToken(tokenInfo.getUserId(), tokenInfo);
            kdocsOAuthService.saveToken("default_user", tokenInfo);
            return htmlPage(true, "授权成功，可关闭此窗口", tokenInfo);
        } catch (Exception e) {
            log.error("OAuth 回调处理失败", e);
            return htmlPage(false, "授权失败: " + e.getMessage(), null);
        }
    }

    private ResponseEntity<String> htmlPage(boolean success, String message, KdocsTokenInfo tokenInfo) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.parseMediaType("text/html;charset=UTF-8"));
        String esc = message.replace("\\", "\\\\").replace("'", "\\'").replace("\n", "\\n").replace("\r", "\\r");
        String uid = tokenInfo != null && tokenInfo.getUserId() != null ? tokenInfo.getUserId().replace("\\", "\\\\").replace("'", "\\'") : "";
        StringBuilder html = new StringBuilder();
        html.append("<!DOCTYPE html><html lang='zh-CN'><head><meta charset='UTF-8'><title>")
            .append(success ? "授权成功" : "授权失败")
            .append("</title></head><body style='font-family:sans-serif;text-align:center;padding:40px'>");
        html.append("<h2>").append(success ? "✓ 授权成功" : "✗ 授权失败").append("</h2>");
        html.append("<p>").append(message).append("</p>");
        html.append("<script>");
        html.append("if(window.opener){window.opener.postMessage({type:'kdocs_oauth_callback',success:")
            .append(success).append(",message:'").append(esc).append("'");
        if (success && !uid.isEmpty()) {
            html.append(",userId:'").append(uid).append("'");
        }
        html.append("},'*');}");
        html.append("setTimeout(function(){if(window.opener)window.close();},2000);");
        html.append("</script></body></html>");
        return new ResponseEntity<>(html.toString(), headers, HttpStatus.OK);
    }

    /**
     * 无授权参数时的占位页：HTTP 200，避免被误判为「回调不可用」，也不向 opener 误发失败消息。
     */
    private ResponseEntity<String> callbackEndpointInfoPage(HttpServletRequest request) {
        return KdocsCallbackProbeResponses.callbackReadyJson(request, null);
    }
}
