"""
TradingAgents市场分析师 - AkShare版本

基于AkShare免费数据源的市场分析师，提供：
- 实时市场概览和趋势分析
- 主要指数和板块分析
- 资金流向和市场情绪分析
- 技术指标和量价分析
- 多市场联动分析 (A股、港股、美股)

@author TradingAgents团队
@version MVP-2.0 (AkShare集成版)
@since 2024-12
"""

import asyncio
import pandas as pd
from datetime import datetime, timedelta
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass
import logging

from langchain.schema import BaseMessage, HumanMessage, SystemMessage
from langchain_openai import ChatOpenAI
from pydantic import BaseModel, Field

from ...dataflows.akshare_adapter import AkShareMasterAdapter, create_akshare_adapter
from ...config.akshare_config import get_akshare_config

logger = logging.getLogger(__name__)


@dataclass
class MarketAnalysisResult:
    """
    市场分析结果数据类
    
    @description 封装市场分析的结构化结果
    """
    timestamp: str
    market_sentiment: str  # BULLISH, BEARISH, NEUTRAL
    confidence_score: float  # 0-1
    key_insights: List[str]
    risk_factors: List[str]
    opportunities: List[str]
    technical_summary: Dict[str, Any]
    fund_flow_summary: Dict[str, Any]
    recommendations: List[str]
    data_sources: List[str]


class MarketSentimentModel(BaseModel):
    """
    市场情绪分析模型
    
    @description 使用Pydantic进行结构化的市场情绪分析
    """
    overall_sentiment: str = Field(description="整体市场情绪: BULLISH/BEARISH/NEUTRAL")
    confidence_level: float = Field(description="信心水平 (0-1)", ge=0, le=1)
    key_drivers: List[str] = Field(description="主要驱动因素")
    risk_assessment: str = Field(description="风险评估: HIGH/MEDIUM/LOW")
    short_term_outlook: str = Field(description="短期展望 (1-7天)")
    medium_term_outlook: str = Field(description="中期展望 (1-4周)")
    sector_rotation: List[str] = Field(description="板块轮动建议")
    market_breadth: str = Field(description="市场广度分析")


class AkShareMarketAnalyst:
    """
    基于AkShare的市场分析师
    
    @description 使用AkShare免费数据源进行全面的市场分析
    """
    
    def __init__(self, llm_model: str = "gpt-4o-mini"):
        """
        初始化市场分析师
        
        @param {str} llm_model - 使用的LLM模型
        """
        self.llm = ChatOpenAI(
            model=llm_model,
            temperature=0.1,
            max_tokens=2000
        )
        
        # 初始化AkShare适配器
        self.akshare_config = get_akshare_config()
        self.data_adapter = create_akshare_adapter(self.akshare_config.data_config)
        
        # 分析师配置
        self.analyst_name = "AkShare市场分析师"
        self.analysis_version = "2.0"
        
        logger.info(f"{self.analyst_name}初始化完成 - 使用100%免费数据源")
    
    async def analyze_market_overview(self) -> MarketAnalysisResult:
        """
        分析市场整体概览
        
        @returns {MarketAnalysisResult} 市场分析结果
        """
        try:
            logger.info("开始市场概览分析...")
            
            # 获取市场数据
            market_data = await self._gather_market_data()
            
            # 进行技术分析
            technical_analysis = await self._perform_technical_analysis(market_data)
            
            # 分析资金流向
            fund_flow_analysis = await self._analyze_fund_flows(market_data)
            
            # 生成LLM分析
            llm_analysis = await self._generate_llm_analysis(
                market_data, technical_analysis, fund_flow_analysis
            )
            
            # 构建分析结果
            result = MarketAnalysisResult(
                timestamp=datetime.now().isoformat(),
                market_sentiment=llm_analysis.overall_sentiment,
                confidence_score=llm_analysis.confidence_level,
                key_insights=llm_analysis.key_drivers,
                risk_factors=[f"风险等级: {llm_analysis.risk_assessment}"],
                opportunities=llm_analysis.sector_rotation,
                technical_summary=technical_analysis,
                fund_flow_summary=fund_flow_analysis,
                recommendations=[
                    llm_analysis.short_term_outlook,
                    llm_analysis.medium_term_outlook,
                    llm_analysis.market_breadth
                ],
                data_sources=["AkShare-A股", "AkShare-指数", "AkShare-资金流向"]
            )
            
            logger.info(f"市场概览分析完成 - 情绪: {result.market_sentiment}")
            return result
            
        except Exception as e:
            logger.error(f"市场概览分析失败: {e}")
            raise
    
    async def analyze_sector_rotation(self) -> Dict[str, Any]:
        """
        分析板块轮动情况
        
        @returns {Dict[str, Any]} 板块轮动分析结果
        """
        try:
            logger.info("开始板块轮动分析...")
            
            # 获取概念资金流向数据
            concept_flow = self.data_adapter.fund_flow.get_concept_fund_flow("即时")
            
            if concept_flow.empty:
                return {"error": "无法获取概念资金流向数据"}
            
            # 分析热门板块
            hot_sectors = concept_flow.nlargest(10, '净额')
            cold_sectors = concept_flow.nsmallest(10, '净额')
            
            # 计算板块强度
            sector_strength = self._calculate_sector_strength(concept_flow)
            
            # 生成轮动建议
            rotation_advice = await self._generate_rotation_advice(
                hot_sectors, cold_sectors, sector_strength
            )
            
            result = {
                "timestamp": datetime.now().isoformat(),
                "hot_sectors": hot_sectors[['行业', '净额', '行业-涨跌幅', '公司家数']].to_dict('records'),
                "cold_sectors": cold_sectors[['行业', '净额', '行业-涨跌幅', '公司家数']].to_dict('records'),
                "sector_strength": sector_strength,
                "rotation_advice": rotation_advice,
                "data_source": "AkShare-概念资金流向"
            }
            
            logger.info(f"板块轮动分析完成 - 热门板块: {len(hot_sectors)}")
            return result
            
        except Exception as e:
            logger.error(f"板块轮动分析失败: {e}")
            return {"error": str(e)}
    
    async def analyze_market_breadth(self) -> Dict[str, Any]:
        """
        分析市场广度
        
        @returns {Dict[str, Any]} 市场广度分析结果
        """
        try:
            logger.info("开始市场广度分析...")
            
            # 获取个股资金流向数据
            individual_flow = self.data_adapter.fund_flow.get_individual_fund_flow("即时")
            
            if individual_flow.empty:
                return {"error": "无法获取个股资金流向数据"}
            
            # 计算市场广度指标
            total_stocks = len(individual_flow)
            rising_stocks = len(individual_flow[individual_flow['涨跌幅'] > 0])
            falling_stocks = len(individual_flow[individual_flow['涨跌幅'] < 0])
            flat_stocks = total_stocks - rising_stocks - falling_stocks
            
            # 计算���金流向分布
            inflow_stocks = len(individual_flow[individual_flow['净额'] > 0])
            outflow_stocks = len(individual_flow[individual_flow['净额'] < 0])
            
            # 计算强势股比例
            strong_stocks = len(individual_flow[
                (individual_flow['涨跌幅'] > 2) & (individual_flow['净额'] > 0)
            ])
            
            # 市场广度评分
            breadth_score = self._calculate_breadth_score(
                rising_stocks, total_stocks, inflow_stocks, strong_stocks
            )
            
            result = {
                "timestamp": datetime.now().isoformat(),
                "total_stocks": total_stocks,
                "market_distribution": {
                    "rising": rising_stocks,
                    "falling": falling_stocks,
                    "flat": flat_stocks,
                    "rising_ratio": rising_stocks / total_stocks
                },
                "fund_flow_distribution": {
                    "inflow_stocks": inflow_stocks,
                    "outflow_stocks": outflow_stocks,
                    "inflow_ratio": inflow_stocks / total_stocks
                },
                "strength_metrics": {
                    "strong_stocks": strong_stocks,
                    "strong_ratio": strong_stocks / total_stocks
                },
                "breadth_score": breadth_score,
                "breadth_assessment": self._assess_market_breadth(breadth_score),
                "data_source": "AkShare-个股资金流向"
            }
            
            logger.info(f"市场广度分析完成 - 广度评分: {breadth_score:.2f}")
            return result
            
        except Exception as e:
            logger.error(f"市场广度分析失败: {e}")
            return {"error": str(e)}
    
    async def _gather_market_data(self) -> Dict[str, Any]:
        """收集市场数据"""
        try:
            # 获取市场概览
            market_overview = self.data_adapter.get_market_overview()
            
            # 获取主要指数历史数据
            indices_history = {}
            major_indices = ["000001", "000300", "399001", "399006"]  # 上证、沪深300、深证、创业板
            
            for index_code in major_indices:
                try:
                    hist_data = self.data_adapter.index.get_index_history(index_code, "1m")
                    if not hist_data.empty:
                        indices_history[index_code] = hist_data.tail(20)  # 最近20天
                except Exception as e:
                    logger.warning(f"获取指数{index_code}历史数据失败: {e}")
            
            return {
                "overview": market_overview,
                "indices_history": indices_history,
                "timestamp": datetime.now().isoformat()
            }
            
        except Exception as e:
            logger.error(f"收集市场数据失败: {e}")
            return {}
    
    async def _perform_technical_analysis(self, market_data: Dict[str, Any]) -> Dict[str, Any]:
        """执行技术分析"""
        try:
            technical_summary = {}
            
            # 分析主要指数的技术指标
            for index_code, hist_data in market_data.get("indices_history", {}).items():
                if hist_data.empty:
                    continue
                
                # 计算技术指标
                indicators = self._calculate_technical_indicators(hist_data)
                technical_summary[index_code] = indicators
            
            # 整体技术评估
            overall_technical = self._assess_overall_technical(technical_summary)
            
            return {
                "individual_indices": technical_summary,
                "overall_assessment": overall_technical,
                "analysis_timestamp": datetime.now().isoformat()
            }
            
        except Exception as e:
            logger.error(f"技术分析失败: {e}")
            return {}
    
    async def _analyze_fund_flows(self, market_data: Dict[str, Any]) -> Dict[str, Any]:
        """分析资金流向"""
        try:
            fund_flow_summary = {}
            
            # 获取概念资金流向
            concept_flow = self.data_adapter.fund_flow.get_concept_fund_flow("即时")
            if not concept_flow.empty:
                fund_flow_summary["concept_flow"] = {
                    "top_inflow": concept_flow.nlargest(5, '净额')[['行业', '净额', '行业-涨跌幅']].to_dict('records'),
                    "top_outflow": concept_flow.nsmallest(5, '净额')[['行业', '净额', '行业-涨跌幅']].to_dict('records'),
                    "total_net_flow": concept_flow['净额'].sum()
                }
            
            # 获取个股资金流向统计
            individual_flow = self.data_adapter.fund_flow.get_individual_fund_flow("即时")
            if not individual_flow.empty:
                fund_flow_summary["individual_flow"] = {
                    "total_inflow": individual_flow[individual_flow['净额'] > 0]['净额'].sum(),
                    "total_outflow": individual_flow[individual_flow['净额'] < 0]['净额'].sum(),
                    "net_flow": individual_flow['净额'].sum(),
                    "active_stocks": len(individual_flow[individual_flow['净额'] != 0])
                }
            
            return fund_flow_summary
            
        except Exception as e:
            logger.error(f"资金流向分析失败: {e}")
            return {}
    
    async def _generate_llm_analysis(
        self, 
        market_data: Dict[str, Any], 
        technical_analysis: Dict[str, Any], 
        fund_flow_analysis: Dict[str, Any]
    ) -> MarketSentimentModel:
        """生成LLM分析"""
        try:
            # 构建分析提示
            analysis_prompt = self._build_analysis_prompt(
                market_data, technical_analysis, fund_flow_analysis
            )
            
            # 调用LLM进行分析
            messages = [
                SystemMessage(content="""你是一位专业的市场分析师，基于AkShare提供的免费数据进行市场分析。
请根据提供的数据进行客观、专业的分析，并以JSON格式返回结构化的分析结果。

分析要求：
1. 综合考虑技术指标、资金流向、市场广度等因素
2. 提供明确的市场情绪判断和信心水平
3. 识别关键的市场驱动因素和风险点
4. 给出短期和中期的市场展望
5. 建议板块轮动策略

请确保分析结果客观、准确，避免过度乐观或悲观。"""),
                HumanMessage(content=analysis_prompt)
            ]
            
            response = await self.llm.ainvoke(messages)
            
            # 解析LLM响应
            import json
            try:
                analysis_result = json.loads(response.content)
                return MarketSentimentModel(**analysis_result)
            except json.JSONDecodeError:
                # 如果JSON解析失败，使用默认值
                return MarketSentimentModel(
                    overall_sentiment="NEUTRAL",
                    confidence_level=0.5,
                    key_drivers=["数据解析异常"],
                    risk_assessment="MEDIUM",
                    short_term_outlook="谨慎观望",
                    medium_term_outlook="保持关注",
                    sector_rotation=["均衡配置"],
                    market_breadth="中性"
                )
            
        except Exception as e:
            logger.error(f"LLM分析失败: {e}")
            return MarketSentimentModel(
                overall_sentiment="NEUTRAL",
                confidence_level=0.3,
                key_drivers=[f"分析异常: {str(e)}"],
                risk_assessment="HIGH",
                short_term_outlook="数据不足",
                medium_term_outlook="需要更多数据",
                sector_rotation=["暂停操作"],
                market_breadth="无法判断"
            )
    
    def _build_analysis_prompt(
        self, 
        market_data: Dict[str, Any], 
        technical_analysis: Dict[str, Any], 
        fund_flow_analysis: Dict[str, Any]
    ) -> str:
        """构建分析提示"""
        prompt = f"""
请基于以下市场数据进行综合分析：

## 市场概览数据
{json.dumps(market_data.get('overview', {}), ensure_ascii=False, indent=2)}

## 技术分析结果
{json.dumps(technical_analysis, ensure_ascii=False, indent=2)}

## 资金流向分析
{json.dumps(fund_flow_analysis, ensure_ascii=False, indent=2)}

请以以下JSON格式返回分析结果：
{{
    "overall_sentiment": "BULLISH/BEARISH/NEUTRAL",
    "confidence_level": 0.0-1.0,
    "key_drivers": ["驱动因素1", "驱动因素2"],
    "risk_assessment": "HIGH/MEDIUM/LOW",
    "short_term_outlook": "短期展望描述",
    "medium_term_outlook": "中期展望描述",
    "sector_rotation": ["建议板块1", "建议板块2"],
    "market_breadth": "市场广度分析"
}}
"""
        return prompt
    
    def _calculate_technical_indicators(self, hist_data: pd.DataFrame) -> Dict[str, Any]:
        """计算技术指标"""
        try:
            if hist_data.empty or len(hist_data) < 10:
                return {}
            
            close_prices = hist_data['close']
            
            # 移动平均线
            ma5 = close_prices.rolling(5).mean().iloc[-1]
            ma10 = close_prices.rolling(10).mean().iloc[-1]
            ma20 = close_prices.rolling(20).mean().iloc[-1] if len(hist_data) >= 20 else None
            
            # RSI
            delta = close_prices.diff()
            gain = (delta.where(delta > 0, 0)).rolling(14).mean()
            loss = (-delta.where(delta < 0, 0)).rolling(14).mean()
            rs = gain / loss
            rsi = 100 - (100 / (1 + rs))
            current_rsi = rsi.iloc[-1] if not rsi.empty else 50
            
            # 当前价格
            current_price = close_prices.iloc[-1]
            
            # 趋势判断
            trend = "NEUTRAL"
            if ma5 > ma10 and current_price > ma5:
                trend = "BULLISH"
            elif ma5 < ma10 and current_price < ma5:
                trend = "BEARISH"
            
            return {
                "current_price": current_price,
                "ma5": ma5,
                "ma10": ma10,
                "ma20": ma20,
                "rsi": current_rsi,
                "trend": trend,
                "price_vs_ma5": (current_price - ma5) / ma5 * 100,
                "price_vs_ma10": (current_price - ma10) / ma10 * 100
            }
            
        except Exception as e:
            logger.error(f"计算技术指标失败: {e}")
            return {}
    
    def _assess_overall_technical(self, technical_summary: Dict[str, Any]) -> Dict[str, Any]:
        """评估整体技术面"""
        try:
            if not technical_summary:
                return {"assessment": "NEUTRAL", "confidence": 0.3}
            
            bullish_count = 0
            bearish_count = 0
            total_count = 0
            
            for index_code, indicators in technical_summary.items():
                if indicators.get("trend"):
                    total_count += 1
                    if indicators["trend"] == "BULLISH":
                        bullish_count += 1
                    elif indicators["trend"] == "BEARISH":
                        bearish_count += 1
            
            if total_count == 0:
                return {"assessment": "NEUTRAL", "confidence": 0.3}
            
            bullish_ratio = bullish_count / total_count
            bearish_ratio = bearish_count / total_count
            
            if bullish_ratio > 0.6:
                assessment = "BULLISH"
                confidence = bullish_ratio
            elif bearish_ratio > 0.6:
                assessment = "BEARISH"
                confidence = bearish_ratio
            else:
                assessment = "NEUTRAL"
                confidence = 0.5
            
            return {
                "assessment": assessment,
                "confidence": confidence,
                "bullish_indices": bullish_count,
                "bearish_indices": bearish_count,
                "total_indices": total_count
            }
            
        except Exception as e:
            logger.error(f"评估整体技术面失败: {e}")
            return {"assessment": "NEUTRAL", "confidence": 0.3}
    
    def _calculate_sector_strength(self, concept_flow: pd.DataFrame) -> Dict[str, Any]:
        """计算板块强度"""
        try:
            if concept_flow.empty:
                return {}
            
            # 计算各种强度指标
            total_sectors = len(concept_flow)
            positive_flow_sectors = len(concept_flow[concept_flow['净额'] > 0])
            strong_sectors = len(concept_flow[
                (concept_flow['净额'] > 0) & (concept_flow['行业-涨跌幅'] > 1)
            ])
            
            # 强度评分
            strength_score = (positive_flow_sectors / total_sectors) * 0.6 + \
                           (strong_sectors / total_sectors) * 0.4
            
            return {
                "total_sectors": total_sectors,
                "positive_flow_sectors": positive_flow_sectors,
                "strong_sectors": strong_sectors,
                "strength_score": strength_score,
                "strength_level": self._assess_strength_level(strength_score)
            }
            
        except Exception as e:
            logger.error(f"计算板块强度失败: {e}")
            return {}
    
    def _assess_strength_level(self, score: float) -> str:
        """评估强度等级"""
        if score >= 0.7:
            return "STRONG"
        elif score >= 0.4:
            return "MODERATE"
        else:
            return "WEAK"
    
    def _calculate_breadth_score(
        self, 
        rising_stocks: int, 
        total_stocks: int, 
        inflow_stocks: int, 
        strong_stocks: int
    ) -> float:
        """计算市场广度评分"""
        try:
            if total_stocks == 0:
                return 0.5
            
            rising_ratio = rising_stocks / total_stocks
            inflow_ratio = inflow_stocks / total_stocks
            strong_ratio = strong_stocks / total_stocks
            
            # 综合评分
            breadth_score = rising_ratio * 0.4 + inflow_ratio * 0.4 + strong_ratio * 0.2
            
            return min(max(breadth_score, 0), 1)  # 限制在0-1范围内
            
        except Exception as e:
            logger.error(f"计算广度评分失败: {e}")
            return 0.5
    
    def _assess_market_breadth(self, score: float) -> str:
        """评估市场广度"""
        if score >= 0.7:
            return "EXCELLENT"
        elif score >= 0.6:
            return "GOOD"
        elif score >= 0.4:
            return "MODERATE"
        elif score >= 0.3:
            return "POOR"
        else:
            return "VERY_POOR"
    
    async def _generate_rotation_advice(
        self, 
        hot_sectors: pd.DataFrame, 
        cold_sectors: pd.DataFrame, 
        sector_strength: Dict[str, Any]
    ) -> List[str]:
        """生成板块轮动建议"""
        try:
            advice = []
            
            # 基于热门板块的建议
            if not hot_sectors.empty:
                top_sector = hot_sectors.iloc[0]
                advice.append(f"关注热门板块: {top_sector['行业']} (净流入: {top_sector['净额']:.2f}亿)")
            
            # 基于冷门板块的建议
            if not cold_sectors.empty:
                bottom_sector = cold_sectors.iloc[0]
                advice.append(f"规避弱势板块: {bottom_sector['行业']} (净流出: {bottom_sector['净额']:.2f}亿)")
            
            # 基于整体强度的建议
            strength_level = sector_strength.get("strength_level", "MODERATE")
            if strength_level == "STRONG":
                advice.append("市场板块轮动活跃，可适当追涨强势板块")
            elif strength_level == "WEAK":
                advice.append("板块分化明显，建议防御性配置")
            else:
                advice.append("板块轮动温和，建议均衡配置")
            
            return advice
            
        except Exception as e:
            logger.error(f"生成轮动建议失败: {e}")
            return ["数据不足，建议谨慎操作"]


# 工厂函数
def create_akshare_market_analyst(llm_model: str = "gpt-4o-mini") -> AkShareMarketAnalyst:
    """
    创建AkShare市场分析师实例
    
    @param {str} llm_model - LLM模型名称
    @returns {AkShareMarketAnalyst} 市场分析师实例
    """
    return AkShareMarketAnalyst(llm_model)


if __name__ == "__main__":
    # 测试市场分析师
    import asyncio
    
    async def test_market_analyst():
        print("=== AkShare市场分析师测试 ===")
        
        # 创建分析师
        analyst = create_akshare_market_analyst()
        
        # 测试市场概览分析
        try:
            overview_result = await analyst.analyze_market_overview()
            print(f"✅ 市场概览分析成功")
            print(f"   市场情绪: {overview_result.market_sentiment}")
            print(f"   信心水平: {overview_result.confidence_score:.2f}")
            print(f"   关键洞察: {len(overview_result.key_insights)}条")
        except Exception as e:
            print(f"❌ 市场概览分析失败: {e}")
        
        # 测试板块轮动分析
        try:
            rotation_result = await analyst.analyze_sector_rotation()
            print(f"✅ 板块轮动分析成功")
            print(f"   热门板块: {len(rotation_result.get('hot_sectors', []))}")
            print(f"   冷门板块: {len(rotation_result.get('cold_sectors', []))}")
        except Exception as e:
            print(f"❌ 板块轮动分析失败: {e}")
        
        # 测试市场广度分析
        try:
            breadth_result = await analyst.analyze_market_breadth()
            print(f"✅ 市场广度分析成功")
            print(f"   总股票数: {breadth_result.get('total_stocks', 0)}")
            print(f"   广度评分: {breadth_result.get('breadth_score', 0):.2f}")
        except Exception as e:
            print(f"❌ 市场广度分析失败: {e}")
        
        print("\n=== AkShare市场分析师测试完成 ===")
    
    # 运行测试
    asyncio.run(test_market_analyst())