package com.dora.service.provider.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dora.dto.provider.*;
import com.dora.dto.runninghub.*;
import com.dora.service.provider.AIProvider;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * RunningHub API适配器
 * 
 * <p>特点：异步API，需要轮询查询结果
 * 
 * @author 1818AI
 * @since 2025-10-20
 */
@Slf4j
@Service("runningHubProvider")
public class RunningHubProviderImpl implements AIProvider {

    private final RestTemplate restTemplate;
    
    @Value("${ai.providers.runninghub.base-url}")
    private String baseUrl;
    
    @Value("${ai.providers.runninghub.submit-url}")
    private String submitUrl;
    
    @Value("${ai.providers.runninghub.status-url}")
    private String statusUrl;
    
    @Value("${ai.providers.runninghub.output-url}")
    private String outputUrl;
    
    @Value("${ai.providers.runninghub.api-key}")
    private String apiKey;
    
    public RunningHubProviderImpl(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public ProviderTaskResponse submitTask(ProviderTaskRequest request) {
        log.info("RunningHub Provider - 提交任务，模型: {}", request.getModelName());
        
        try {
            // 1. 从providerConfig中解析配置
            Map<String, Object> config = request.getProviderConfig();
            String webappId = (String) config.get("webappId");
            String taskType = (String) config.get("taskType");  // text2video, image2video 或 image_to_video
            String model = (String) config.get("model");
            Integer duration = config.get("duration") != null ? 
                    ((Number) config.get("duration")).intValue() : 10;
            
            // 2. 构建nodeInfoList
            List<RunningHubNodeInfo> nodeInfoList = new ArrayList<>();
            
            // 判断是否为图生视频（支持多种格式）
            boolean isImage2Video = "image2video".equals(taskType) || "image_to_video".equals(taskType);
            
            if (isImage2Video) {
                // 图生视频：需要添加image节点
                String imageValue = request.getImageUrl();
                if (imageValue == null || imageValue.trim().isEmpty()) {
                    imageValue = request.getImageBase64();
                }
                
                if (imageValue == null || imageValue.trim().isEmpty()) {
                    throw new IllegalArgumentException("图生视频任务必须提供imageUrl或imageBase64");
                }
                
                // 图片节点（nodeId="2"）
                nodeInfoList.add(RunningHubNodeInfo.builder()
                        .nodeId("2")
                        .fieldName("image")
                        .fieldValue(imageValue)  // 可以是完整URL或文件名
                        .description("上传图像（不支持真人做图像的输入）")
                        .build());
                
                // 提示词节点（nodeId="1"，在图生视频中可选）
                if (request.getPrompt() != null && !request.getPrompt().trim().isEmpty()) {
                    nodeInfoList.add(RunningHubNodeInfo.builder()
                            .nodeId("1")
                            .fieldName("prompt")
                            .fieldValue(request.getPrompt())
                            .description("输入文本")
                            .build());
                }
            } else {
                // 文生视频：只需要prompt
                nodeInfoList.add(RunningHubNodeInfo.builder()
                        .nodeId("1")
                        .fieldName("prompt")
                        .fieldValue(request.getPrompt())
                        .description("输入文本")
                        .build());
            }
            
            // 模型节点（横竖屏）- 两种任务都需要
            nodeInfoList.add(RunningHubNodeInfo.builder()
                    .nodeId("1")
                    .fieldName("model")
                    .fieldValue(model)
                    .fieldData(buildModelFieldData())
                    .description("横竖模式")
                    .build());
            
            // 时长节点 - 两种任务都需要
            nodeInfoList.add(RunningHubNodeInfo.builder()
                    .nodeId("1")
                    .fieldName("duration_seconds")
                    .fieldValue(String.valueOf(duration))
                    .fieldData("[[10, 15], {\"default\": 10}]")
                    .description("时长（秒）")
                    .build());
            
            // 3. 构建请求
            RunningHubSubmitRequest submitRequest = RunningHubSubmitRequest.builder()
                    .webappId(webappId)
                    .apiKey(apiKey)
                    .nodeInfoList(nodeInfoList)
                    .build();
            
            // 4. 发送请求
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Host", "www.runninghub.cn");
            
            HttpEntity<RunningHubSubmitRequest> entity = new HttpEntity<>(submitRequest, headers);
            
            String url = baseUrl + submitUrl;
            log.info("RunningHub Provider - 请求URL: {}", url);
            log.info("RunningHub Provider - 请求体: {}", JSON.toJSONString(submitRequest));
            
            ResponseEntity<RunningHubSubmitResponse> response = restTemplate.postForEntity(
                    url, entity, RunningHubSubmitResponse.class
            );
            
            RunningHubSubmitResponse submitResponse = response.getBody();
            
            // 打印完整响应
            log.info("RunningHub Provider - 提交任务响应: {}", JSON.toJSONString(submitResponse));
            
            // 5. 解析响应
            if (submitResponse == null || submitResponse.getCode() != 0) {
                String errorMsg = submitResponse != null ? submitResponse.getMsg() : "响应为空";
                log.error("RunningHub Provider - 提交失败: code={}, msg={}", 
                         submitResponse != null ? submitResponse.getCode() : null, errorMsg);
                return ProviderTaskResponse.builder()
                        .status(ProviderTaskResponse.TaskSubmitStatus.FAILED)
                        .errorMessage("RunningHub提交失败: " + errorMsg)
                        .build();
            }
            
            RunningHubSubmitResponse.SubmitData data = submitResponse.getData();
            log.info("RunningHub Provider - 任务已提交成功，taskId: {}, status: {}, clientId: {}, wssUrl: {}", 
                     data.getTaskId(), data.getTaskStatus(), data.getClientId(), data.getNetWssUrl());
            
            // 6. 构建响应
            Map<String, Object> rawResponse = new HashMap<>();
            rawResponse.put("taskId", data.getTaskId());
            rawResponse.put("clientId", data.getClientId());
            rawResponse.put("taskStatus", data.getTaskStatus());
            rawResponse.put("netWssUrl", data.getNetWssUrl());
            
            return ProviderTaskResponse.builder()
                    .providerTaskId(data.getTaskId())
                    .status(ProviderTaskResponse.TaskSubmitStatus.PROCESSING)
                    .websocketUrl(data.getNetWssUrl())
                    .clientId(data.getClientId())
                    .rawResponse(rawResponse)
                    .build();
            
        } catch (Exception e) {
            log.error("RunningHub Provider - 提交任务异常: {}", e.getMessage(), e);
            return ProviderTaskResponse.builder()
                    .status(ProviderTaskResponse.TaskSubmitStatus.FAILED)
                    .errorMessage("提交RunningHub任务失败: " + e.getMessage())
                    .build();
        }
    }

    @Override
    public ProviderTaskStatus queryTaskStatus(String providerTaskId) {
        log.info("RunningHub Provider - 查询任务状态，taskId: {}", providerTaskId);
        
        try {
            // 构建请求
            Map<String, String> requestBody = new HashMap<>();
            requestBody.put("apiKey", apiKey);
            requestBody.put("taskId", providerTaskId);
            
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Host", "www.runninghub.cn");
            
            HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, headers);
            
            String url = baseUrl + statusUrl;
            log.info("RunningHub Provider - 查询状态请求: URL={}, body={}", url, JSON.toJSONString(requestBody));
            
            ResponseEntity<RunningHubStatusResponse> response = restTemplate.postForEntity(
                    url, entity, RunningHubStatusResponse.class
            );
            
            RunningHubStatusResponse statusResponse = response.getBody();
            
            // 打印完整响应
            log.info("RunningHub Provider - 查询状态响应: {}", JSON.toJSONString(statusResponse));
            
            if (statusResponse == null || statusResponse.getCode() != 0) {
                log.warn("RunningHub Provider - 查询状态失败: code={}, msg={}", 
                         statusResponse != null ? statusResponse.getCode() : null,
                         statusResponse != null ? statusResponse.getMsg() : "响应为空");
                return ProviderTaskStatus.builder()
                        .providerTaskId(providerTaskId)
                        .status(ProviderTaskStatus.Status.UNKNOWN)
                        .errorMessage(statusResponse != null ? statusResponse.getMsg() : "查询失败")
                        .build();
            }
            
            // 映射状态
            String rhStatus = statusResponse.getData();
            ProviderTaskStatus.Status mappedStatus = mapRunningHubStatus(rhStatus);
            
            log.info("RunningHub Provider - 任务状态: taskId={}, rhStatus={}, mappedStatus={}", 
                     providerTaskId, rhStatus, mappedStatus);
            
            return ProviderTaskStatus.builder()
                    .providerTaskId(providerTaskId)
                    .status(mappedStatus)
                    .build();
            
        } catch (Exception e) {
            log.error("RunningHub Provider - 查询状态异常: {}", e.getMessage(), e);
            return ProviderTaskStatus.builder()
                    .providerTaskId(providerTaskId)
                    .status(ProviderTaskStatus.Status.UNKNOWN)
                    .errorMessage(e.getMessage())
                    .build();
        }
    }

    @Override
    public ProviderTaskResult getTaskResult(String providerTaskId) {
        log.info("RunningHub Provider - 获取任务结果，taskId: {}", providerTaskId);
        
        try {
            // 构建请求
            Map<String, String> requestBody = new HashMap<>();
            requestBody.put("apiKey", apiKey);
            requestBody.put("taskId", providerTaskId);
            
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Host", "www.runninghub.cn");
            
            HttpEntity<Map<String, String>> entity = new HttpEntity<>(requestBody, headers);
            
            String url = baseUrl + outputUrl;
            log.info("RunningHub Provider - 获取结果请求: URL={}, body={}", url, JSON.toJSONString(requestBody));
            
            ResponseEntity<RunningHubOutputResponse> response = restTemplate.postForEntity(
                    url, entity, RunningHubOutputResponse.class
            );
            
            RunningHubOutputResponse outputResponse = response.getBody();
            
            // 打印完整响应
            log.info("RunningHub Provider - 获取结果响应: {}", JSON.toJSONString(outputResponse));
            
            if (outputResponse == null || outputResponse.getCode() != 0) {
                log.error("RunningHub Provider - 获取结果失败: code={}, msg={}", 
                          outputResponse != null ? outputResponse.getCode() : null,
                          outputResponse != null ? outputResponse.getMsg() : "响应为空");
                return ProviderTaskResult.builder()
                        .providerTaskId(providerTaskId)
                        .success(false)
                        .errorMessage(outputResponse != null ? outputResponse.getMsg() : "获取结果失败")
                        .build();
            }
            
            // 转换文件列表
            List<ProviderTaskResult.ResultFile> files = outputResponse.getData().stream()
                    .map(f -> ProviderTaskResult.ResultFile.builder()
                            .fileUrl(f.getFileUrl())
                            .fileType(f.getFileType())
                            .nodeId(f.getNodeId())
                            .build())
                    .collect(Collectors.toList());
            
            log.info("RunningHub Provider - 成功获取{}个结果文件，详情: {}", 
                     files.size(), 
                     files.stream().map(ProviderTaskResult.ResultFile::getFileUrl).collect(Collectors.toList()));
            
            return ProviderTaskResult.builder()
                    .providerTaskId(providerTaskId)
                    .success(true)
                    .files(files)
                    .build();
            
        } catch (Exception e) {
            log.error("RunningHub Provider - 获取结果异常: {}", e.getMessage(), e);
            return ProviderTaskResult.builder()
                    .providerTaskId(providerTaskId)
                    .success(false)
                    .errorMessage(e.getMessage())
                    .build();
        }
    }

    @Override
    public String getProviderName() {
        return "runninghub";
    }

    @Override
    public boolean isAsyncProvider() {
        return true;  // RunningHub是异步API
    }

    /**
     * 构建模型字段数据
     */
    private String buildModelFieldData() {
        return "[{\"name\":\"portrait\",\"index\":\"portrait\",\"description\":\"竖屏\",\"fastIndex\":1.0,\"descriptionEn\":\"Vertical screen\"}," +
               "{\"name\":\"landscape\",\"index\":\"landscape\",\"description\":\"横屏\",\"fastIndex\":2.0,\"descriptionEn\":\"Horizontal screen\"}," +
               "{\"name\":\"portrait-hd\",\"index\":\"portrait-hd\",\"description\":\"高清竖屏\",\"fastIndex\":3.0,\"descriptionEn\":\"HD vertical screen\"}," +
               "{\"name\":\"landscape-hd\",\"index\":\"landscape-hd\",\"description\":\"高清横屏\",\"fastIndex\":4.0,\"descriptionEn\":\"HD horizontal screen\"}]";
    }

    /**
     * 映射RunningHub状态到统一状态
     */
    private ProviderTaskStatus.Status mapRunningHubStatus(String rhStatus) {
        if (rhStatus == null) {
            return ProviderTaskStatus.Status.UNKNOWN;
        }
        
        switch (rhStatus) {
            case "QUEUED":
                return ProviderTaskStatus.Status.QUEUED;
            case "RUNNING":
                return ProviderTaskStatus.Status.RUNNING;
            case "SUCCESS":
                return ProviderTaskStatus.Status.SUCCESS;
            case "FAILED":
                return ProviderTaskStatus.Status.FAILED;
            default:
                return ProviderTaskStatus.Status.UNKNOWN;
        }
    }
}

