package com.dora.controller;

import com.dora.common.Result;
import com.dora.entity.PointsConfig;
import com.dora.entity.SystemConfig;
import com.dora.service.AdminConfigService;
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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

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

/**
 * 管理端 - 系统与积分配置管理控制器
 * 
 * 提供以下功能：
 * 1. AI模型积分价格配置管理（增删改查）
 * 2. 系统参数配置管理（队列、超时等）
 * 
 * @author 1818AI
 * @since 2025-10-19
 */
@Slf4j
@RestController
@RequestMapping("/admin/configs")
@Tag(name = "系统与积分配置管理", description = "管理端API - 用于管理AI模型的积分定价和系统运行参数")
@RequiredArgsConstructor
@PreAuthorize("hasRole('ADMIN')")
public class AdminConfigController {

    private final AdminConfigService adminConfigService;

    // ==================== 积分配置管理 ====================

    /**
     * 获取所有AI模型的积分配置
     * 
     * @return 积分配置列表
     */
    @GetMapping("/points")
    @Operation(
        summary = "获取所有积分配置", 
        description = "查询所有AI模型的积分价格配置列表，包括已启用和已禁用的模型"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功"),
        @ApiResponse(responseCode = "401", description = "未授权 - 需要管理员登录"),
        @ApiResponse(responseCode = "403", description = "禁止访问 - 需要ADMIN角色")
    })
    public Result<List<PointsConfig>> getAllPointsConfigs() {
        log.info("管理员查询所有积分配置");
        List<PointsConfig> configs = adminConfigService.getAllPointsConfigs();
        log.info("成功查询到 {} 条积分配置记录", configs.size());
        return Result.success(configs);
    }

    /**
     * 创建新的AI模型积分配置
     * 
     * @param pointsConfig 积分配置对象
     * @return 创建成功的积分配置
     */
    @PostMapping("/points")
    @Operation(
        summary = "创建积分配置", 
        description = "为新的AI模型添加积分价格配置。模型名称（modelName）必须唯一。"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "创建成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误 - 模型名称重复或必填字段缺失"),
        @ApiResponse(responseCode = "401", description = "未授权"),
        @ApiResponse(responseCode = "403", description = "禁止访问")
    })
    public Result<PointsConfig> createPointsConfig(
            @Parameter(description = "积分配置对象，包含模型名称、积分价格、描述等信息", required = true)
            @RequestBody PointsConfig pointsConfig) {
        log.info("管理员创建新的积分配置，模型名称: {}, 积分价格: {}", 
                 pointsConfig.getModelName(), pointsConfig.getPointsCost());
        
        PointsConfig createdConfig = adminConfigService.createPointsConfig(pointsConfig);
        
        log.info("成功创建积分配置，ID: {}, 模型: {}", 
                 createdConfig.getId(), createdConfig.getModelName());
        
        return Result.success(createdConfig, "创建成功");
    }

    /**
     * 更新现有AI模型的积分配置
     * 
     * @param id 积分配置ID
     * @param pointsConfig 更新的积分配置对象
     * @return 更新后的积分配置
     */
    @PutMapping("/points/{id}")
    @Operation(
        summary = "更新积分配置", 
        description = "修改指定AI模型的积分价格或其他配置。常用于调整模型定价或启用/禁用模型。"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "更新成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误"),
        @ApiResponse(responseCode = "404", description = "未找到指定的配置"),
        @ApiResponse(responseCode = "401", description = "未授权"),
        @ApiResponse(responseCode = "403", description = "禁止访问")
    })
    public Result<PointsConfig> updatePointsConfig(
            @Parameter(description = "积分配置ID", required = true, example = "1")
            @PathVariable Long id,
            @Parameter(description = "更新的积分配置对象", required = true)
            @RequestBody PointsConfig pointsConfig) {
        log.info("管理员更新积分配置，ID: {}, 新价格: {}", id, pointsConfig.getPointsCost());
        
        PointsConfig updatedConfig = adminConfigService.updatePointsConfig(id, pointsConfig);
        
        log.info("成功更新积分配置，ID: {}, 模型: {}, 新价格: {}", 
                 updatedConfig.getId(), updatedConfig.getModelName(), updatedConfig.getPointsCost());
        
        return Result.success(updatedConfig, "更新成功");
    }

    /**
     * 删除AI模型的积分配置
     * 
     * @param id 积分配置ID
     * @return 无内容响应
     */
    @DeleteMapping("/points/{id}")
    @Operation(
        summary = "删除积分配置", 
        description = "逻辑删除指定的AI模型积分配置。删除后该模型将无法被用户调用。注意：这是软删除，数据库记录仍然保留。"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "删除成功"),
        @ApiResponse(responseCode = "404", description = "未找到指定的配置"),
        @ApiResponse(responseCode = "401", description = "未授权"),
        @ApiResponse(responseCode = "403", description = "禁止访问")
    })
    public Result<Void> deletePointsConfig(
            @Parameter(description = "积分配置ID", required = true, example = "8")
            @PathVariable Long id) {
        log.info("管理员删除积分配置，ID: {}", id);
        
        adminConfigService.deletePointsConfig(id);
        
        log.info("成功删除积分配置，ID: {}", id);
        
        return Result.success(null, "删除成功");
    }

    // ==================== 系统配置管理 ====================

    /**
     * 获取所有系统配置参数
     * 
     * @return 系统配置列表
     */
    @GetMapping("/system")
    @Operation(
        summary = "获取所有系统配置", 
        description = "查询所有系统级配置参数，如队列并发数、任务超时时间等。这些配置会影响系统的运行行为。"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "查询成功"),
        @ApiResponse(responseCode = "401", description = "未授权"),
        @ApiResponse(responseCode = "403", description = "禁止访问")
    })
    public Result<List<SystemConfig>> getAllSystemConfigs() {
        log.info("管理员查询所有系统配置");
        List<SystemConfig> configs = adminConfigService.getAllSystemConfigs();
        log.info("成功查询到 {} 条系统配置记录", configs.size());
        return Result.success(configs);
    }

    /**
     * 批量更新系统配置参数
     * 
     * @param configs 配置键值对映射（key-value格式）
     * @return 无内容响应
     */
    @PutMapping("/system")
    @Operation(
        summary = "更新系统配置", 
        description = "批量更新一个或多个系统配置参数。" +
                      "请求体应为JSON格式的键值对，如：{\"ai.queue.max_concurrent\": \"100\"}。" +
                      "修改后的配置会立即生效（通过缓存刷新机制）。"
    )
    @ApiResponses(value = {
        @ApiResponse(responseCode = "200", description = "更新成功"),
        @ApiResponse(responseCode = "400", description = "请求参数错误 - 配置键不存在或格式错误"),
        @ApiResponse(responseCode = "401", description = "未授权"),
        @ApiResponse(responseCode = "403", description = "禁止访问")
    })
    public Result<Void> updateSystemConfigs(
            @Parameter(
                description = "系统配置键值对。" +
                              "常用配置键：" +
                              "ai.queue.max_concurrent (最大并发数)、" +
                              "ai.queue.max_user_concurrent (单用户最大并发)、" +
                              "ai.task.timeout_minutes (任务超时分钟数)", 
                required = true,
                example = "{\"ai.queue.max_concurrent\": \"100\", \"ai.task.timeout_minutes\": \"15\"}"
            )
            @RequestBody Map<String, String> configs) {
        log.info("管理员批量更新系统配置，更新数量: {}", configs.size());
        
        configs.forEach((key, value) -> {
            log.info("更新系统配置: {} = {}", key, value);
            adminConfigService.updateSystemConfig(key, value);
        });
        
        log.info("成功批量更新系统配置");
        
        return Result.success(null, "更新成功");
    }
}
