package com.dora.service.impl;

import com.dora.dto.AiModelDto;
import com.dora.entity.PointsConfig;
import com.dora.mapper.PointsConfigMapper;
import com.dora.service.AiModelService;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * AI模型查询服务实现（用户端）
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AiModelServiceImpl implements AiModelService {

    private final PointsConfigMapper pointsConfigMapper;
    private final ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public List<AiModelDto.ModelInfoResponse> getAllModels(String taskType, String providerType, Boolean enabledOnly) {
        // 查询模型列表
        List<PointsConfig> configs;
        
        boolean hasTaskType = taskType != null && !taskType.trim().isEmpty();
        boolean hasProvider = providerType != null && !providerType.trim().isEmpty();
        
        if (hasTaskType && hasProvider) {
            // 同时按任务类型和厂商查询
            configs = pointsConfigMapper.findByProviderAndTaskType(providerType, taskType, enabledOnly);
        } else if (hasTaskType) {
            // 只按任务类型查询
            configs = pointsConfigMapper.findByTaskType(taskType, enabledOnly);
        } else if (hasProvider) {
            // 只按厂商查询
            configs = pointsConfigMapper.findByProviderType(providerType, enabledOnly);
        } else if (enabledOnly != null && enabledOnly) {
            // 只查询已启用的
            configs = pointsConfigMapper.findAllEnabled();
        } else {
            // 查询全部
            configs = pointsConfigMapper.findAll();
        }

        // 转换为DTO
        return configs.stream()
                .map(this::convertToModelInfo)
                .collect(Collectors.toList());
    }

    @Override
    public List<AiModelDto.ModelsByTypeResponse> getModelsByType(String providerType, Boolean enabledOnly) {
        // 获取所有模型
        List<AiModelDto.ModelInfoResponse> allModels = getAllModels(null, providerType, enabledOnly);

        // 按任务类型分组
        Map<String, List<AiModelDto.ModelInfoResponse>> groupedByType = allModels.stream()
                .collect(Collectors.groupingBy(AiModelDto.ModelInfoResponse::getTaskType));

        // 转换为响应DTO
        return groupedByType.entrySet().stream()
                .map(entry -> AiModelDto.ModelsByTypeResponse.builder()
                        .taskType(entry.getKey())
                        .taskTypeName(getTaskTypeName(entry.getKey()))
                        .models(entry.getValue())
                        .count(entry.getValue().size())
                        .build())
                .sorted(Comparator.comparing(AiModelDto.ModelsByTypeResponse::getTaskType))
                .collect(Collectors.toList());
    }

    @Override
    public List<AiModelDto.ModelsByProviderResponse> getModelsByProvider(String taskType, Boolean enabledOnly) {
        // 获取所有模型
        List<AiModelDto.ModelInfoResponse> allModels = getAllModels(taskType, null, enabledOnly);

        // 按厂商分组
        Map<String, List<AiModelDto.ModelInfoResponse>> groupedByProvider = allModels.stream()
                .collect(Collectors.groupingBy(AiModelDto.ModelInfoResponse::getProviderType));

        // 转换为响应DTO
        return groupedByProvider.entrySet().stream()
                .map(entry -> AiModelDto.ModelsByProviderResponse.builder()
                        .providerType(entry.getKey())
                        .providerName(getProviderName(entry.getKey()))
                        .models(entry.getValue())
                        .count(entry.getValue().size())
                        .build())
                .sorted(Comparator.comparing(AiModelDto.ModelsByProviderResponse::getProviderType))
                .collect(Collectors.toList());
    }

    @Override
    public AiModelDto.ModelStatsResponse getModelStats() {
        List<PointsConfig> allConfigs = pointsConfigMapper.findAll();
        List<PointsConfig> enabledConfigs = allConfigs.stream()
                .filter(config -> config.getIsEnabled() == 1)
                .collect(Collectors.toList());

        // 按类型统计（优先使用数据库的 task_type）
        Map<String, Integer> countByType = new HashMap<>();
        for (PointsConfig config : enabledConfigs) {
            String taskType = config.getTaskType();
            if (taskType == null || taskType.trim().isEmpty()) {
                taskType = inferTaskType(config.getModelName());
            }
            countByType.put(taskType, countByType.getOrDefault(taskType, 0) + 1);
        }

        // 按厂商统计
        Map<String, Integer> countByProvider = enabledConfigs.stream()
                .collect(Collectors.groupingBy(
                        config -> config.getProviderType() != null ? config.getProviderType() : "unknown",
                        Collectors.collectingAndThen(Collectors.counting(), Long::intValue)
                ));

        return AiModelDto.ModelStatsResponse.builder()
                .totalModels(allConfigs.size())
                .enabledModels(enabledConfigs.size())
                .countByType(countByType)
                .countByProvider(countByProvider)
                .build();
    }

    // ==================== 私有方法 ====================

    /**
     * 转换为模型信息DTO
     */
    private AiModelDto.ModelInfoResponse convertToModelInfo(PointsConfig config) {
        // 优先使用数据库中的 task_type，如果没有则根据模型名称推断
        String taskType = config.getTaskType();
        if (taskType == null || taskType.trim().isEmpty()) {
            taskType = inferTaskType(config.getModelName());
        }
        
        String displayName = generateDisplayName(config.getModelName(), config.getDescription());
        Map<String, Object> extendedConfig = parseExtendedConfig(config.getProviderConfig());

        return AiModelDto.ModelInfoResponse.builder()
                .id(config.getId())
                .modelName(config.getModelName())
                .displayName(displayName)
                .description(config.getDescription())
                .pointsCost(config.getPointsCost())
                .providerType(config.getProviderType() != null ? config.getProviderType() : "unknown")
                .taskType(taskType)
                .isEnabled(config.getIsEnabled() == 1)
                .extendedConfig(extendedConfig)
                .build();
    }

    /**
     * 从模型名称推断任务类型
     */
    private String inferTaskType(String modelName) {
        if (modelName == null) {
            return "unknown";
        }
        
        String lowerName = modelName.toLowerCase();
        
        // 视频相关关键词
        if (lowerName.contains("video") || lowerName.contains("sora") && lowerName.contains("2")) {
            return "video";
        }
        
        // 图片相关关键词
        if (lowerName.contains("image") || lowerName.contains("img") || 
            lowerName.contains("picture") || lowerName.contains("photo") ||
            (lowerName.contains("sora") && !lowerName.contains("video"))) {
            return "image";
        }
        
        // 音频相关关键词
        if (lowerName.contains("audio") || lowerName.contains("music") || lowerName.contains("sound")) {
            return "audio";
        }
        
        // 文本相关关键词
        if (lowerName.contains("text") || lowerName.contains("gpt") || lowerName.contains("chat")) {
            return "text";
        }
        
        return "other";
    }

    /**
     * 判断模型名称是否匹配任务类型
     */
    private boolean matchesTaskType(String modelName, String taskType) {
        String inferredType = inferTaskType(modelName);
        return inferredType.equalsIgnoreCase(taskType);
    }

    /**
     * 生成显示名称
     */
    private String generateDisplayName(String modelName, String description) {
        if (description != null && !description.trim().isEmpty()) {
            // 如果有描述，优先使用描述
            return description;
        }
        
        // 否则对模型名称进行格式化
        if (modelName == null) {
            return "未知模型";
        }
        
        // 简单的格式化：将下划线替换为空格，首字母大写
        return Arrays.stream(modelName.split("[_-]"))
                .map(word -> word.substring(0, 1).toUpperCase() + word.substring(1).toLowerCase())
                .collect(Collectors.joining(" "));
    }

    /**
     * 解析扩展配置
     */
    private Map<String, Object> parseExtendedConfig(String providerConfig) {
        if (providerConfig == null || providerConfig.trim().isEmpty()) {
            return new HashMap<>();
        }
        
        try {
            return objectMapper.readValue(providerConfig, new TypeReference<Map<String, Object>>() {});
        } catch (Exception e) {
            log.warn("解析providerConfig失败: {}", providerConfig, e);
            return new HashMap<>();
        }
    }

    /**
     * 获取任务类型名称
     */
    private String getTaskTypeName(String taskType) {
        if (taskType == null) return "未知";
        
        switch (taskType.toLowerCase()) {
            case "text_to_image":
                return "文生图";
            case "image_to_image":
                return "图生图";
            case "text_to_video":
                return "文生视频";
            case "image_to_video":
                return "图生视频";
            case "llm":
                return "大语言模型";
            case "text_to_audio":
                return "文生音频";
            case "image_to_text":
                return "图生文";
            case "image":
                return "图片生成";
            case "video":
                return "视频生成";
            case "audio":
                return "音频生成";
            case "text":
                return "文本生成";
            default:
                return "其他";
        }
    }

    /**
     * 获取提供商名称
     */
    private String getProviderName(String providerType) {
        if (providerType == null) return "未知";
        
        switch (providerType.toLowerCase()) {
            case "openai":
                return "OpenAI";
            case "runninghub":
                return "RunningHub";
            case "anthropic":
                return "Anthropic";
            case "google":
                return "Google";
            default:
                return providerType;
        }
    }
}

