package com.dora.service;

import com.alibaba.fastjson.JSON;
import com.dora.dto.api.ApiResponse;
import com.dora.entity.AiTask;
import com.dora.entity.PointsConfig;
import com.dora.mapper.PointsConfigMapper;
import com.dora.service.provider.AIProvider;
import com.dora.dto.provider.ProviderTaskRequest;
import com.dora.dto.provider.ProviderTaskResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

@Service
@Slf4j
@RequiredArgsConstructor
public class AsyncTaskExecutor {

    private final AIProviderService aiProviderService;
    private final PointsConfigMapper pointsConfigMapper;

    /**
     * 异步执行AI生成任务的API调用（使用新的Provider架构）
     * 
     * <p>这个方法使用新的Provider架构，根据模型配置自动路由到正确的AI服务提供商：
     * <ul>
     *   <li>OpenAI Provider：处理OpenAI兼容的模型</li>
     *   <li>RunningHub Provider：处理RunningHub Sora2模型（异步）</li>
     *   <li>SuChuang Provider：处理速创API模型（异步）</li>
     * </ul>
     * 
     * @param task 要执行的任务实体
     * @return 包含API响应的CompletableFuture，如果发生异常则为failed状态
     */
    @Async("taskExecutor")
    public CompletableFuture<ApiResponse> executeApiCall(AiTask task) {
        log.info("开始异步调用API，任务编号: {}, 模型: {}, Provider类型: {}", 
                 task.getTaskNo(), task.getModelName(), task.getProviderType());
        
        try {
            // 1. 获取对应的Provider
            AIProvider provider = aiProviderService.getProvider(task.getModelName());
            log.info("任务 {} 使用Provider: {}", task.getTaskNo(), provider.getProviderName());
            
            // 2. 构建Provider请求
            ProviderTaskRequest request = buildProviderRequest(task);
            
            // 3. 调用Provider
            if (provider.isAsyncProvider()) {
                // 异步Provider（RunningHub, SuChuang）：提交任务并返回taskId
                ProviderTaskResponse response = provider.submitTask(request);
                
                // 检查响应是否有效
                if (response == null || response.getProviderTaskId() == null || response.getProviderTaskId().trim().isEmpty()) {
                    log.error("异步任务 {} 提交失败，Provider返回无效响应: {}", task.getTaskNo(), response);
                    throw new RuntimeException("出现一点小错误，本次积分已回退");
                }
                
                log.info("异步任务 {} 提交成功，Provider任务ID: {}", task.getTaskNo(), response.getProviderTaskId());
                
                // 转换为ApiResponse格式（兼容现有逻辑）
                // 使用ApiResponse的id字段来存储providerTaskId
                ApiResponse apiResponse = new ApiResponse();
                apiResponse.setId(response.getProviderTaskId());
                apiResponse.setModel(task.getModelName());
                
                return CompletableFuture.completedFuture(apiResponse);
            } else {
                // 同步Provider（OpenAI）：直接返回结果
                log.error("同步Provider暂不支持通过AsyncTaskExecutor调用，任务: {}", task.getTaskNo());
                throw new UnsupportedOperationException("同步Provider应该直接调用，不通过AsyncTaskExecutor");
            }
            
        } catch (Exception e) {
            log.error("任务 {} 在Provider调用期间发生异常: {}", task.getTaskNo(), e.getMessage(), e);
            return CompletableFuture.failedFuture(e);
        }
    }
    
    /**
     * 构建Provider请求对象
     */
    private ProviderTaskRequest buildProviderRequest(AiTask task) {
        ProviderTaskRequest request = new ProviderTaskRequest();
        request.setModelName(task.getModelName());
        request.setPrompt(task.getPrompt());
        request.setImageUrl(task.getImageUrl());
        request.setImageBase64(task.getImageBase64());
        request.setAspectRatio(task.getAspectRatio());
        
        // 从数据库获取模型的provider_config
        Map<String, Object> providerConfig = getProviderConfig(task.getModelName());
        request.setProviderConfig(providerConfig);
        
        // 处理续作参数：从 providerResponse 中提取 tempSourcePid
        if (task.getProviderResponse() != null && task.getProviderResponse().contains("tempSourcePid")) {
            try {
                com.alibaba.fastjson.JSONObject json = com.alibaba.fastjson.JSON.parseObject(task.getProviderResponse());
                String sourcePid = json.getString("tempSourcePid");
                if (sourcePid != null) {
                    Map<String, Object> extraParams = new java.util.HashMap<>();
                    extraParams.put("sourcePid", sourcePid);
                    request.setExtraParams(extraParams);
                    log.info("任务 {} 包含续作PID: {}", task.getTaskNo(), sourcePid);
                }
            } catch (Exception e) {
                log.warn("解析续作参数失败: {}", e.getMessage());
            }
        }
        
        return request;
    }
    
    /**
     * 从数据库获取模型的provider_config
     */
    private Map<String, Object> getProviderConfig(String modelName) {
        try {
            PointsConfig pointsConfig = pointsConfigMapper.findByModelName(modelName);
            if (pointsConfig == null) {
                log.warn("未找到模型配置，modelName: {}", modelName);
                return null;
            }
            
            String providerConfigJson = pointsConfig.getProviderConfig();
            Map<String, Object> config;
            
            if (providerConfigJson == null || providerConfigJson.trim().isEmpty()) {
                // 如果JSON配置为空，创建一个新的Map
                config = new HashMap<>();
                log.info("模型配置为空，创建新配置，modelName: {}", modelName);
            } else {
                // 解析JSON配置
                @SuppressWarnings("unchecked")
                Map<String, Object> parsedConfig = JSON.parseObject(providerConfigJson, Map.class);
                config = parsedConfig != null ? parsedConfig : new HashMap<>();
            }
            
            // 添加taskType到providerConfig中，确保provider能正确识别任务类型
            if (pointsConfig.getTaskType() != null) {
                config.put("taskType", pointsConfig.getTaskType());
            }
            
            log.info("获取到模型配置，modelName: {}, config: {}", modelName, config);
            return config;
            
        } catch (Exception e) {
            log.error("获取provider_config失败，modelName: {}", modelName, e);
            return null;
        }
    }
}
