package com.ruoyi.web.controller.jarvis;

import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.jarvis.domain.dto.KdocsTokenInfo;
import com.ruoyi.jarvis.service.IKdocsOAuthService;
import com.ruoyi.jarvis.service.IKdocsOpenApiService;
import com.ruoyi.jarvis.service.impl.KdocsOAuthServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

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

/**
 * 金山文档个人云（developer.kdocs.cn）
 */
@RestController
@RequestMapping("/jarvis/kdocs")
public class KdocsCloudController extends BaseController {

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

    @Autowired
    private IKdocsOAuthService kdocsOAuthService;
    @Autowired
    private IKdocsOpenApiService kdocsOpenApiService;
    @Autowired
    private KdocsOAuthServiceImpl kdocsOAuthServiceImpl;

    @GetMapping("/authUrl")
    public AjaxResult getAuthUrl(@RequestParam(required = false) String state) {
        try {
            return AjaxResult.success("获取授权URL成功", kdocsOAuthService.getAuthUrl(state));
        } catch (Exception e) {
            log.error("获取授权URL失败", e);
            return AjaxResult.error("获取授权URL失败: " + e.getMessage());
        }
    }

    @Anonymous
    @GetMapping("/oauth/callback")
    public AjaxResult oauthCallback(@RequestParam String code, @RequestParam(required = false) String state) {
        try {
            KdocsTokenInfo tokenInfo = kdocsOAuthService.getAccessTokenByCode(code);
            if (tokenInfo.getUserId() != null) {
                kdocsOAuthService.saveToken(tokenInfo.getUserId(), tokenInfo);
                kdocsOAuthService.saveToken("default_user", tokenInfo);
            }
            return AjaxResult.success("授权成功", tokenInfo);
        } catch (Exception e) {
            log.error("OAuth回调失败", e);
            return AjaxResult.error("授权失败: " + e.getMessage());
        }
    }

    @PostMapping("/refreshToken")
    public AjaxResult refreshToken(@RequestBody Map<String, Object> params) {
        try {
            String refreshToken = (String) params.get("refreshToken");
            String userId = (String) params.get("userId");
            if (StringUtils.isBlank(refreshToken)) {
                return AjaxResult.error("refreshToken不能为空");
            }
            if (StringUtils.isBlank(userId)) {
                userId = "default_user";
            }
            KdocsTokenInfo tokenInfo = kdocsOAuthService.refreshAccessToken(refreshToken, userId);
            kdocsOAuthService.saveToken(userId, tokenInfo);
            if (!userId.equals(tokenInfo.getUserId()) && tokenInfo.getUserId() != null) {
                kdocsOAuthService.saveToken(tokenInfo.getUserId(), tokenInfo);
            }
            kdocsOAuthService.saveToken("default_user", tokenInfo);
            return AjaxResult.success("刷新令牌成功", tokenInfo);
        } catch (Exception e) {
            log.error("刷新访问令牌失败", e);
            return AjaxResult.error("刷新令牌失败: " + e.getMessage());
        }
    }

    @GetMapping("/tokenStatus")
    public AjaxResult getTokenStatus(@RequestParam(required = false) String userId) {
        try {
            KdocsTokenInfo tokenInfo = null;
            if (StringUtils.isNotBlank(userId)) {
                tokenInfo = kdocsOAuthServiceImpl.getTokenByUserId(userId);
                if (tokenInfo == null && "default_user".equals(userId)) {
                    tokenInfo = kdocsOAuthService.getCurrentToken();
                    if (tokenInfo != null) {
                        kdocsOAuthService.saveToken("default_user", tokenInfo);
                    }
                }
            } else {
                tokenInfo = kdocsOAuthService.getCurrentToken();
            }
            if (tokenInfo == null) {
                JSONObject r = new JSONObject();
                r.put("hasToken", false);
                r.put("isValid", false);
                return AjaxResult.success("未授权", r);
            }
            boolean valid = kdocsOAuthService.isTokenValid(tokenInfo);
            JSONObject r = new JSONObject();
            r.put("hasToken", true);
            r.put("isValid", valid);
            r.put("userId", tokenInfo.getUserId());
            r.put("expired", tokenInfo.isExpired());
            if (tokenInfo.getExpiresIn() != null) {
                r.put("expiresIn", tokenInfo.getExpiresIn());
            }
            return AjaxResult.success("获取Token状态成功", r);
        } catch (Exception e) {
            log.error("获取Token状态失败", e);
            return AjaxResult.error("获取Token状态失败: " + e.getMessage());
        }
    }

    @PostMapping("/setToken")
    public AjaxResult setToken(@RequestBody Map<String, Object> params) {
        try {
            String accessToken = (String) params.get("accessToken");
            String refreshToken = (String) params.get("refreshToken");
            String userId = (String) params.get("userId");
            Integer expiresIn = params.get("expiresIn") != null
                ? Integer.valueOf(params.get("expiresIn").toString()) : 86400;
            if (StringUtils.isBlank(accessToken)) {
                return AjaxResult.error("accessToken不能为空");
            }
            if (StringUtils.isBlank(userId)) {
                return AjaxResult.error("userId不能为空");
            }
            KdocsTokenInfo info = new KdocsTokenInfo();
            info.setAccessToken(accessToken);
            info.setRefreshToken(refreshToken);
            info.setExpiresIn(expiresIn);
            info.setUserId(userId);
            kdocsOAuthService.saveToken(userId, info);
            return AjaxResult.success("设置Token成功");
        } catch (Exception e) {
            log.error("设置Token失败", e);
            return AjaxResult.error("设置Token失败: " + e.getMessage());
        }
    }

    private KdocsTokenInfo ensureToken(String userId) {
        KdocsTokenInfo tokenInfo = kdocsOAuthServiceImpl.getTokenByUserId(userId);
        if (tokenInfo == null) {
            throw new IllegalStateException("用户未授权，请先完成授权");
        }
        if (tokenInfo.isExpired() && tokenInfo.getRefreshToken() != null) {
            tokenInfo = kdocsOAuthService.refreshAccessToken(tokenInfo.getRefreshToken(), userId);
            kdocsOAuthService.saveToken(userId, tokenInfo);
            kdocsOAuthService.saveToken("default_user", tokenInfo);
        }
        return tokenInfo;
    }

    @GetMapping("/userInfo")
    public AjaxResult getUserInfo(@RequestParam String userId) {
        try {
            KdocsTokenInfo t = ensureToken(userId);
            JSONObject userInfo = kdocsOpenApiService.getUserInfoFlat(t.getAccessToken());
            return AjaxResult.success("获取用户信息成功", userInfo);
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("获取用户信息失败", e);
            return AjaxResult.error("获取用户信息失败: " + e.getMessage());
        }
    }

    @GetMapping("/files")
    public AjaxResult getFileList(@RequestParam String userId,
                                  @RequestParam(required = false, defaultValue = "1") Integer page,
                                  @RequestParam(required = false, defaultValue = "20") Integer pageSize,
                                  @RequestParam(required = false) Integer next_offset,
                                  @RequestParam(required = false) String next_filter) {
        try {
            KdocsTokenInfo t = ensureToken(userId);
            Map<String, Object> p = new java.util.HashMap<>();
            p.put("page", page);
            p.put("page_size", pageSize);
            p.put("pageSize", pageSize);
            if (next_offset != null) {
                p.put("next_offset", next_offset);
            }
            if (next_filter != null) {
                p.put("next_filter", next_filter);
            }
            JSONObject fileList = kdocsOpenApiService.getFileList(t.getAccessToken(), p);
            return AjaxResult.success("获取文件列表成功", fileList);
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("获取文件列表失败", e);
            return AjaxResult.error("获取文件列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/fileInfo")
    public AjaxResult getFileInfo(@RequestParam String userId, @RequestParam String fileToken) {
        try {
            KdocsTokenInfo t = ensureToken(userId);
            return AjaxResult.success("获取文件信息成功", kdocsOpenApiService.getFileInfo(t.getAccessToken(), fileToken));
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("获取文件信息失败", e);
            return AjaxResult.error("获取文件信息失败: " + e.getMessage());
        }
    }

    @GetMapping("/sheets")
    public AjaxResult getSheetList(@RequestParam String userId, @RequestParam String fileToken) {
        try {
            KdocsTokenInfo t = ensureToken(userId);
            return AjaxResult.success("获取工作表列表成功", kdocsOpenApiService.getSheetList(t.getAccessToken(), fileToken));
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("获取工作表列表失败", e);
            return AjaxResult.error("获取工作表列表失败: " + e.getMessage());
        }
    }

    @GetMapping("/readCells")
    public AjaxResult readCells(@RequestParam String userId,
                                @RequestParam String fileToken,
                                @RequestParam(defaultValue = "0") int sheetIdx,
                                @RequestParam(required = false) String range) {
        try {
            KdocsTokenInfo t = ensureToken(userId);
            JSONObject data = kdocsOpenApiService.readCells(t.getAccessToken(), fileToken, sheetIdx, range);
            return AjaxResult.success("读取单元格数据成功", data);
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("读取单元格失败", e);
            return AjaxResult.error("读取单元格数据失败: " + e.getMessage());
        }
    }

    @PostMapping("/updateCells")
    public AjaxResult updateCells(@RequestBody Map<String, Object> params) {
        try {
            String userId = (String) params.get("userId");
            String fileToken = (String) params.get("fileToken");
            int sheetIdx = params.get("sheetIdx") != null ? Integer.parseInt(params.get("sheetIdx").toString()) : 0;
            String range = (String) params.get("range");
            @SuppressWarnings("unchecked")
            List<List<Object>> values = (List<List<Object>>) params.get("values");
            if (userId == null || fileToken == null || range == null || values == null || values.isEmpty()) {
                return AjaxResult.error("userId、fileToken、range、values 不能为空");
            }
            KdocsTokenInfo t = ensureToken(userId);
            JSONObject r = kdocsOpenApiService.updateCells(t.getAccessToken(), fileToken, sheetIdx, range, values);
            return AjaxResult.success("更新单元格数据成功", r);
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("更新单元格失败", e);
            return AjaxResult.error("更新单元格数据失败: " + e.getMessage());
        }
    }

    @PostMapping("/createSheet")
    public AjaxResult createSheet(@RequestBody Map<String, Object> params) {
        try {
            String userId = (String) params.get("userId");
            String fileToken = (String) params.get("fileToken");
            String sheetName = (String) params.get("sheetName");
            if (userId == null || fileToken == null || sheetName == null) {
                return AjaxResult.error("userId、fileToken、sheetName 不能为空");
            }
            KdocsTokenInfo t = ensureToken(userId);
            return AjaxResult.success("创建数据表成功", kdocsOpenApiService.createSheet(t.getAccessToken(), fileToken, sheetName));
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("创建数据表失败", e);
            return AjaxResult.error("创建数据表失败: " + e.getMessage());
        }
    }

    @PostMapping("/batchUpdateCells")
    public AjaxResult batchUpdateCells(@RequestBody Map<String, Object> params) {
        try {
            String userId = (String) params.get("userId");
            String fileToken = (String) params.get("fileToken");
            int sheetIdx = params.get("sheetIdx") != null ? Integer.parseInt(params.get("sheetIdx").toString()) : 0;
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> updates = (List<Map<String, Object>>) params.get("updates");
            if (userId == null || fileToken == null || updates == null || updates.isEmpty()) {
                return AjaxResult.error("参数不完整");
            }
            KdocsTokenInfo t = ensureToken(userId);
            return AjaxResult.success("批量更新成功", kdocsOpenApiService.batchUpdateCells(t.getAccessToken(), fileToken, sheetIdx, updates));
        } catch (IllegalStateException e) {
            return AjaxResult.error(e.getMessage());
        } catch (Exception e) {
            log.error("批量更新失败", e);
            return AjaxResult.error("批量更新单元格数据失败: " + e.getMessage());
        }
    }
}
