"""
TradingAgents 混合配置系统
===========================

混合配置策略：
- 优先使用免费数据源（降低成本）
- 付费数据源作为fallback（确保数据质量）
- 智能切换和缓存机制

成本对比：
- 纯付费方案：~$197/月
- 混合方案：~$30/月（节省85%）
- 纯免费方案：~$10/月（仅OpenAI费用）

@author TradingAgents团队
@version MVP-1.0
@since 2024-12
"""

import os
from typing import Dict, Any, List, Optional
from dataclasses import dataclass
import logging
from dotenv import load_dotenv

# 加载环境变量
load_dotenv()

logger = logging.getLogger(__name__)

@dataclass 
class HybridDataConfig:
    """
    混合数据源配置类
    
    @description 统一管理免费和付费数据源的配置参数
    """
    # 免费数据源配置
    use_free_fundamentals: bool = True
    use_free_news: bool = True
    use_free_technical: bool = True
    
    # Alpha Vantage配置（免费层）
    alpha_vantage_key: Optional[str] = None
    av_daily_limit: int = 500
    av_enable_fallback: bool = True
    
    # Reddit API配置（社交媒体情绪分析）
    reddit_client_id: Optional[str] = None
    reddit_enable: bool = True
    
    # OpenAI API配置
    openai_api_key: Optional[str] = None
    
    # 付费数据源配置（作为fallback）
    finnhub_api_key: Optional[str] = None
    finnhub_enable_fallback: bool = True
    
    # 智能切换策略
    data_quality_threshold: float = 0.8  # 数据质量阈值
    fallback_timeout_seconds: int = 30
    max_retry_attempts: int = 3
    
    # 缓存配置
    cache_ttl_hours: int = 6
    enable_intelligent_cache: bool = True
    cache_db_path: str = "data/cache/hybrid_cache.db"
    
    # 性能配置
    concurrent_requests: int = 3
    request_delay_seconds: float = 0.5
    
    def __post_init__(self):
        """初始化后处理"""
        # 从环境变量获取API密钥
        if not self.alpha_vantage_key:
            self.alpha_vantage_key = os.getenv("ALPHA_VANTAGE_API_KEY")
        
        if not self.reddit_client_id:
            self.reddit_client_id = os.getenv("REDDIT_CLIENT_ID")
            
        if not self.openai_api_key:
            self.openai_api_key = os.getenv("OPENAI_API_KEY")
        
        if not self.finnhub_api_key:
            self.finnhub_api_key = os.getenv("FINNHUB_API_KEY")
        
        # 确保缓存目录存在
        os.makedirs(os.path.dirname(self.cache_db_path), exist_ok=True)


# 预定义配置方案
HYBRID_CONFIGURATIONS = {
    "cost_optimized": HybridDataConfig(
        use_free_fundamentals=True,
        use_free_news=True,
        use_free_technical=True,
        finnhub_enable_fallback=False,  # 完全免费模式
        cache_ttl_hours=12,  # 更长缓存时间
        av_daily_limit=450   # 保留50次缓冲
    ),
    
    "balanced": HybridDataConfig(
        use_free_fundamentals=True,
        use_free_news=True,
        use_free_technical=True,
        finnhub_enable_fallback=True,   # 付费fallback
        cache_ttl_hours=6,
        av_daily_limit=400
    ),
    
    "quality_first": HybridDataConfig(
        use_free_fundamentals=False,
        use_free_news=True,
        use_free_technical=True,
        finnhub_enable_fallback=True,
        data_quality_threshold=0.9,
        cache_ttl_hours=3,
        av_daily_limit=500
    ),
    
    "development": HybridDataConfig(
        use_free_fundamentals=True,
        use_free_news=True,
        use_free_technical=True,
        finnhub_enable_fallback=False,
        cache_ttl_hours=24,  # 开发环境长缓存
        av_daily_limit=100   # 开发环境低限制
    )
}


class HybridConfigManager:
    """
    混合配置管理器
    
    @description 管理数据源切换策略和配置动态调整
    @version MVP-1.0
    """
    
    def __init__(self, config_name: str = "balanced"):
        """
        初始化配置管理器
        
        @param {str} config_name - 配置方案名称
        """
        if config_name not in HYBRID_CONFIGURATIONS:
            logger.warning(f"未知配置方案: {config_name}，使用默认balanced配置")
            config_name = "balanced"
        
        self.config = HYBRID_CONFIGURATIONS[config_name]
        self.config_name = config_name
        self.runtime_stats = {
            "free_success_rate": 0.0,
            "fallback_usage_rate": 0.0,
            "avg_response_time": 0.0,
            "daily_api_calls": 0
        }
        
        logger.info(f"混合配置已初始化: {config_name}")
    
    def should_use_free_source(self, data_type: str) -> bool:
        """
        判断是否应该使用免费数据源
        
        @param {str} data_type - 数据类型 (fundamentals/news/technical)
        @returns {bool} 是否使用免费源
        """
        if data_type == "fundamentals":
            return self.config.use_free_fundamentals
        elif data_type == "news":
            return self.config.use_free_news
        elif data_type == "technical":
            return self.config.use_free_technical
        else:
            return True  # 默认使用免费源
    
    def should_enable_fallback(self, data_type: str) -> bool:
        """
        判断是否启用付费数据源作为fallback
        
        @param {str} data_type - 数据类型
        @returns {bool} 是否启用fallback
        """
        base_fallback = self.config.finnhub_enable_fallback
        
        # 根据运行时统计调整fallback策略
        if self.runtime_stats["free_success_rate"] < self.config.data_quality_threshold:
            logger.info(f"免费源成功率过低({self.runtime_stats['free_success_rate']:.2f})，启用fallback")
            return True
        
        return base_fallback
    
    def can_use_alpha_vantage(self) -> bool:
        """
        检查是否可以使用Alpha Vantage API
        
        @returns {bool} 是否可以使用
        """
        if not self.config.alpha_vantage_key:
            return False
        
        if self.runtime_stats["daily_api_calls"] >= self.config.av_daily_limit:
            logger.warning("Alpha Vantage日调用限制已达到")
            return False
        
        return True
    
    def update_runtime_stats(self, success: bool, response_time: float, used_fallback: bool):
        """
        更新运行时统计信息
        
        @param {bool} success - 请求是否成功
        @param {float} response_time - 响应时间
        @param {bool} used_fallback - 是否使用了fallback
        """
        # 简化统计更新逻辑
        if success:
            self.runtime_stats["free_success_rate"] = min(
                self.runtime_stats["free_success_rate"] + 0.01, 1.0
            )
        else:
            self.runtime_stats["free_success_rate"] = max(
                self.runtime_stats["free_success_rate"] - 0.05, 0.0
            )
        
        if used_fallback:
            self.runtime_stats["fallback_usage_rate"] += 0.01
        
        # 更新平均响应时间
        current_avg = self.runtime_stats["avg_response_time"]
        self.runtime_stats["avg_response_time"] = (current_avg * 0.9) + (response_time * 0.1)
        
        # 增加API调用计数
        self.runtime_stats["daily_api_calls"] += 1
    
    def get_data_source_priority(self, data_type: str) -> List[str]:
        """
        获取数据源优先级列表
        
        @param {str} data_type - 数据类型
        @returns {List[str]} 按优先级排序的数据源列表
        """
        sources = []
        
        if self.should_use_free_source(data_type):
            if data_type == "fundamentals":
                sources.extend(["sec_edgar", "yahoo_finance"])
                if self.can_use_alpha_vantage():
                    sources.append("alpha_vantage")
            elif data_type == "news":
                sources.extend(["yahoo_news", "rss_aggregator"])
            elif data_type == "technical":
                sources.append("yahoo_finance")
                if self.can_use_alpha_vantage():
                    sources.append("alpha_vantage")
        
        # 添加付费fallback源
        if self.should_enable_fallback(data_type) and self.config.finnhub_api_key:
            if data_type == "fundamentals":
                sources.append("finnhub_fundamentals")
            elif data_type == "news":
                sources.append("finnhub_news")
        
        return sources
    
    def get_cache_config(self) -> Dict[str, Any]:
        """
        获取缓存配置
        
        @returns {Dict[str, Any]} 缓存配置字典
        """
        return {
            "ttl_hours": self.config.cache_ttl_hours,
            "db_path": self.config.cache_db_path,
            "intelligent_cache": self.config.enable_intelligent_cache
        }
    
    def get_performance_config(self) -> Dict[str, Any]:
        """
        获取性能配置
        
        @returns {Dict[str, Any]} 性能配置字典
        """
        return {
            "concurrent_requests": self.config.concurrent_requests,
            "request_delay": self.config.request_delay_seconds,
            "timeout": self.config.fallback_timeout_seconds,
            "max_retries": self.config.max_retry_attempts
        }
    
    def adapt_config_based_on_performance(self):
        """
        根据性能表现自适应调整配置
        """
        # 如果免费源成功率太低，增加缓存时间
        if self.runtime_stats["free_success_rate"] < 0.5:
            self.config.cache_ttl_hours = min(self.config.cache_ttl_hours * 2, 24)
            logger.info(f"由于免费源成功率低，增加缓存时间至{self.config.cache_ttl_hours}小时")
        
        # 如果响应时间过长，减少并发请求
        if self.runtime_stats["avg_response_time"] > 10.0:
            self.config.concurrent_requests = max(self.config.concurrent_requests - 1, 1)
            logger.info(f"由于响应时间过长，减少并发请求至{self.config.concurrent_requests}")
        
        # 如果API调用过多，启用更积极的缓存
        if self.runtime_stats["daily_api_calls"] > self.config.av_daily_limit * 0.8:
            self.config.cache_ttl_hours = min(self.config.cache_ttl_hours * 1.5, 24)
            logger.info("API调用接近限制，增加缓存时间")
    
    def export_config(self) -> Dict[str, Any]:
        """
        导出当前配置为字典
        
        @returns {Dict[str, Any]} 配置字典
        """
        return {
            "config_name": self.config_name,
            "free_sources": {
                "fundamentals": self.config.use_free_fundamentals,
                "news": self.config.use_free_news,
                "technical": self.config.use_free_technical
            },
            "api_keys": {
                "alpha_vantage": bool(self.config.alpha_vantage_key),
                "finnhub": bool(self.config.finnhub_api_key)
            },
            "limits": {
                "av_daily_limit": self.config.av_daily_limit,
                "quality_threshold": self.config.data_quality_threshold
            },
            "cache": self.get_cache_config(),
            "performance": self.get_performance_config(),
            "runtime_stats": self.runtime_stats
        }
    
    def print_config_summary(self):
        """打印配置摘要"""
        print(f"\n🔧 TradingAgents 混合配置摘要")
        print(f"==========================================")
        print(f"配置方案: {self.config_name}")
        print(f"免费基本面: {'✅' if self.config.use_free_fundamentals else '❌'}")
        print(f"免费新闻: {'✅' if self.config.use_free_news else '❌'}")
        print(f"免费技术指标: {'✅' if self.config.use_free_technical else '❌'}")
        print(f"Alpha Vantage: {'✅' if self.config.alpha_vantage_key else '❌'}")
        print(f"FinnHub Fallback: {'✅' if self.config.finnhub_enable_fallback else '❌'}")
        print(f"缓存时间: {self.config.cache_ttl_hours}小时")
        print(f"日API限制: {self.config.av_daily_limit}次")
        print(f"并发请求: {self.config.concurrent_requests}")
        
        # 估算月成本
        monthly_cost = self._estimate_monthly_cost()
        print(f"💰 预估月成本: ${monthly_cost:.2f}")
        print(f"==========================================\n")
    
    def _estimate_monthly_cost(self) -> float:
        """估算月度成本"""
        base_cost = 20.0  # OpenAI基础费用
        
        if self.config.finnhub_enable_fallback and self.config.finnhub_api_key:
            # 如果启用FinnHub fallback，增加部分费用
            fallback_usage = self.runtime_stats.get("fallback_usage_rate", 0.1)
            base_cost += 197 * fallback_usage  # 按使用比例计算
        
        return base_cost


def create_hybrid_config(config_name: str = "balanced") -> HybridConfigManager:
    """
    创建混合配置管理器的便捷函数
    
    @param {str} config_name - 配置方案名称
    @returns {HybridConfigManager} 配置管理器实例
    """
    return HybridConfigManager(config_name)


def list_available_configs() -> List[str]:
    """
    列出所有可用的配置方案
    
    @returns {List[str]} 配置方案名称列表
    """
    return list(HYBRID_CONFIGURATIONS.keys())


def print_all_configs():
    """打印所有配置方案的详细信息"""
    print("\n📋 TradingAgents 可用配置方案")
    print("=" * 50)
    
    for name, config in HYBRID_CONFIGURATIONS.items():
        print(f"\n🔸 {name.upper()}")
        print(f"   免费基本面: {'✅' if config.use_free_fundamentals else '❌'}")
        print(f"   免费新闻: {'✅' if config.use_free_news else '❌'}")
        print(f"   付费Fallback: {'✅' if config.finnhub_enable_fallback else '❌'}")
        print(f"   缓存时间: {config.cache_ttl_hours}小时")
        print(f"   Alpha Vantage限制: {config.av_daily_limit}次/日")
        
        # 估算成本
        if name == "cost_optimized":
            cost = "$10-20/月"
        elif name == "balanced":
            cost = "$20-40/月"
        elif name == "quality_first":
            cost = "$40-80/月"
        else:
            cost = "$10-15/月"
        
        print(f"   💰 预估成本: {cost}")
    
    print("=" * 50)


if __name__ == "__main__":
    # 演示配置系统
    print("🚀 TradingAgents 混合配置系统演示")
    
    # 显示所有配置
    print_all_configs()
    
    # 创建平衡配置
    manager = create_hybrid_config("balanced")
    manager.print_config_summary()
    
    # 测试数据源优先级
    print("📊 数据源优先级测试:")
    for data_type in ["fundamentals", "news", "technical"]:
        sources = manager.get_data_source_priority(data_type)
        print(f"  {data_type}: {' → '.join(sources)}")
    
    # 导出配置
    config_dict = manager.export_config()
    print(f"\n📤 配置导出成功: {len(config_dict)}个配置项") 