package com.dora.controller;

import com.dora.common.Result;
import com.dora.dto.ToolDto;
import com.dora.exception.InsufficientPointsException;
import com.dora.service.ToolService;
import com.dora.util.SecurityUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

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

/**
 * 工具服务控制器（用户端）
 * 
 * 提供以下功能：
 * 1. 获取可用工具列表
 * 2. 调用工具（自动扣除积分）
 * 3. 查看调用记录
 * 
 * 支持两种认证方式：
 * - JWT Token（Web端登录用户）
 * - API Key（开发者调用）
 * 
 * @author 1818AI
 * @since 2026-01-02
 */
@Slf4j
@RestController
@RequestMapping("/user/tools")
@Tag(name = "工具服务（用户端）", description = "用户调用各类数据采集工具的接口，支持JWT和API Key两种认证方式")
@RequiredArgsConstructor
public class ToolController {

    private final ToolService toolService;

    /**
     * 获取所有可用工具列表
     */
    @GetMapping("/list")
    @Operation(
        summary = "获取工具列表", 
        description = "获取所有可用的工具列表，包含工具名称、分类、积分消耗等信息。\n\n" +
                      "**认证方式**：\n" +
                      "- JWT Token（Web端）：登录后自动使用\n" +
                      "- API Key（开发者）：在请求头添加 `Authorization: Bearer {your_api_key}`"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "401", description = "未认证 - 请提供JWT Token或API Key")
    })
    public Result<List<ToolDto.ToolListItem>> getToolList() {
        try {
            // 验证用户认证（支持JWT和API Key）
            SecurityUtil.getCurrentUserId();
            
            List<ToolDto.ToolListItem> tools = toolService.getAvailableTools();
            return Result.success(tools);
        } catch (com.dora.exception.AuthenticationException e) {
            log.warn("用户未认证: {}", e.getMessage());
            return Result.error(401, "未认证，请提供有效的JWT Token或API Key");
        } catch (Exception e) {
            log.error("获取工具列表失败", e);
            return Result.error("获取工具列表失败: " + e.getMessage());
        }
    }

    /**
     * 按分类获取工具列表
     */
    @GetMapping("/list/{category}")
    @Operation(
        summary = "按分类获取工具", 
        description = "按分类获取工具列表。\n\n" +
                      "**支持的分类**：\n" +
                      "- douyin: 抖音相关工具\n" +
                      "- xiaohongshu: 小红书相关工具\n" +
                      "- wechat_mp: 微信公众号相关工具\n\n" +
                      "**认证方式**：JWT Token 或 API Key"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "401", description = "未认证")
    })
    public Result<List<ToolDto.ToolListItem>> getToolsByCategory(
            @Parameter(description = "工具分类（douyin/xiaohongshu/wechat_mp）", example = "douyin")
            @PathVariable String category) {
        try {
            SecurityUtil.getCurrentUserId();
            
            List<ToolDto.ToolListItem> tools = toolService.getToolsByCategory(category);
            return Result.success(tools);
        } catch (com.dora.exception.AuthenticationException e) {
            log.warn("用户未认证: {}", e.getMessage());
            return Result.error(401, "未认证，请提供有效的JWT Token或API Key");
        } catch (Exception e) {
            log.error("获取分类工具列表失败: category={}", category, e);
            return Result.error("获取工具列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取工具详情
     */
    @GetMapping("/detail/{toolCode}")
    @Operation(
        summary = "获取工具详情", 
        description = "获取指定工具的详细信息，包括工具名称、描述、积分消耗等。\n\n" +
                      "**认证方式**：JWT Token 或 API Key"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "401", description = "未认证"),
            @ApiResponse(responseCode = "404", description = "工具不存在")
    })
    public Result<ToolDto.ToolListItem> getToolDetail(
            @Parameter(description = "工具编码", example = "douyin_user_videos")
            @PathVariable String toolCode) {
        try {
            SecurityUtil.getCurrentUserId();
            
            ToolDto.ToolListItem tool = toolService.getToolDetail(toolCode);
            return Result.success(tool);
        } catch (com.dora.exception.AuthenticationException e) {
            log.warn("用户未认证: {}", e.getMessage());
            return Result.error(401, "未认证，请提供有效的JWT Token或API Key");
        } catch (Exception e) {
            log.error("获取工具详情失败: toolCode={}", toolCode, e);
            return Result.error("获取工具详情失败: " + e.getMessage());
        }
    }

    /**
     * 调用工具
     */
    @PostMapping("/call/{toolCode}")
    @Operation(
        summary = "调用工具", 
        description = "调用指定工具，系统会自动扣除对应的积分。\n\n" +
                      "**认证方式**：\n" +
                      "- JWT Token（Web端）：登录后自动使用\n" +
                      "- API Key（开发者）：在请求头添加 `Authorization: Bearer {your_api_key}`\n\n" +
                      "**调用流程**：\n" +
                      "1. 验证用户认证\n" +
                      "2. 检查用户积分是否充足\n" +
                      "3. 扣除积分\n" +
                      "4. 调用第三方API\n" +
                      "5. 返回结果（如果调用失败会自动退还积分）\n\n" +
                      "**请求参数示例（抖音获取用户视频）**：\n" +
                      "```json\n" +
                      "{\n" +
                      "  \"sec_user_id\": \"MS4wLjABAAAA...\",\n" +
                      "  \"max_cursor\": 0,\n" +
                      "  \"count\": 20\n" +
                      "}\n" +
                      "```"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "调用成功"),
            @ApiResponse(responseCode = "400", description = "参数错误或工具不存在"),
            @ApiResponse(responseCode = "401", description = "未认证 - 请提供JWT Token或API Key"),
            @ApiResponse(responseCode = "402", description = "积分不足 - 请先充值")
    })
    public Result<ToolDto.CallResponse> callTool(
            @Parameter(description = "工具编码", required = true, example = "douyin_user_videos")
            @PathVariable String toolCode,
            @Parameter(description = "请求参数，根据不同工具传入不同参数")
            @RequestBody Map<String, Object> params,
            HttpServletRequest request) {
        try {
            // 从Spring Security上下文获取当前用户ID（支持JWT和API Key两种方式）
            Long userId = SecurityUtil.getCurrentUserId();
            String clientIp = getClientIp(request);
            
            log.info("用户 {} 调用工具: {}, 参数: {}", userId, toolCode, params);
            
            ToolDto.CallResponse response = toolService.callTool(userId, toolCode, params, clientIp);
            
            log.info("工具调用成功: userId={}, toolCode={}, usageNo={}, pointsCost={}", 
                    userId, toolCode, response.getUsageNo(), response.getPointsCost());
            
            return Result.success(response);
        } catch (com.dora.exception.AuthenticationException e) {
            log.warn("用户未认证: {}", e.getMessage());
            return Result.error(401, "未认证，请提供有效的JWT Token或API Key");
        } catch (InsufficientPointsException e) {
            log.warn("用户积分不足: {}", e.getMessage());
            return Result.error(402, "积分不足：" + e.getMessage());
        } catch (IllegalArgumentException e) {
            log.warn("工具调用参数错误: {}", e.getMessage());
            return Result.error(400, "参数错误：" + e.getMessage());
        } catch (Exception e) {
            log.error("调用工具失败: toolCode={}", toolCode, e);
            return Result.error(500, "调用工具失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户的工具调用记录
     */
    @GetMapping("/usage/logs")
    @Operation(
        summary = "获取调用记录", 
        description = "获取当前用户的工具调用记录，支持分页和按工具筛选。\n\n" +
                      "**认证方式**：JWT Token 或 API Key"
    )
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "查询成功"),
            @ApiResponse(responseCode = "401", description = "未认证")
    })
    public Result<ToolDto.UsageLogPageResponse> getUsageLogs(
            @Parameter(description = "页码", example = "1")
            @RequestParam(defaultValue = "1") Integer page,
            @Parameter(description = "每页数量", example = "10")
            @RequestParam(defaultValue = "10") Integer size,
            @Parameter(description = "工具编码（可选，用于筛选特定工具的记录）")
            @RequestParam(required = false) String toolCode) {
        try {
            Long userId = SecurityUtil.getCurrentUserId();
            
            log.info("用户 {} 查询工具调用记录: page={}, size={}, toolCode={}", userId, page, size, toolCode);
            
            ToolDto.UsageLogPageResponse logs = toolService.getUserUsageLogs(userId, page, size, toolCode);
            return Result.success(logs);
        } catch (com.dora.exception.AuthenticationException e) {
            log.warn("用户未认证: {}", e.getMessage());
            return Result.error(401, "未认证，请提供有效的JWT Token或API Key");
        } catch (Exception e) {
            log.error("获取调用记录失败", e);
            return Result.error("获取调用记录失败: " + e.getMessage());
        }
    }

    /**
     * 获取客户端IP
     */
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 多个代理时取第一个IP
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}
