# -*- coding: utf-8 -*-
"""
估值指标分析器
用于判断股票应该使用PE估值还是PB估值更合理
"""

import sys
import os
import logging
from typing import Dict, Any, Optional, Tuple
from datetime import datetime

# 添加项目根目录到 Python 路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))

from src.valuation_analysis.valuation_chat_bot import ValuationChatBot
from src.scripts.config import get_random_api_key, get_model

# 设置日志
logger = logging.getLogger(__name__)

class ValuationIndicatorAnalyzer:
    """估值指标分析器"""
    
    def __init__(self):
        """初始化分析器"""
        try:
            # 初始化联网大模型（使用专用估值分析聊天机器人）
            self.online_chatbot = ValuationChatBot(model_type="online_bot")
            
            # 初始化本地GLM模型（使用专用估值分析离线聊天机器人）
            try:
                from src.valuation_analysis.valuation_chat_bot import ValuationOfflineChatBot
                self.offline_chatbot = ValuationOfflineChatBot(model_type="offline_bot")
                self.has_offline_model = True
            except ImportError:
                logger.warning("无法导入离线模型，将只使用联网模型")
                self.offline_chatbot = None
                self.has_offline_model = False
                
            logger.info("估值指标分析器初始化成功")
            
        except Exception as e:
            logger.error(f"初始化估值指标分析器失败: {str(e)}")
            raise
    
    def analyze_valuation_indicator(self, stock_code: str, stock_name: str) -> Dict[str, Any]:
        """
        分析股票应该使用PE还是PB估值
        
        Args:
            stock_code: 股票代码
            stock_name: 股票名称
            
        Returns:
            Dict包含分析结果
        """
        try:
            logger.info(f"开始分析股票 {stock_name}({stock_code}) 的估值指标")
            
            # 第一步：使用联网大模型进行初步分析
            online_result = self._analyze_with_online_model(stock_code, stock_name)
            
            # 第二步：使用本地GLM模型进行格式化和验证
            if self.has_offline_model:
                offline_result = self._analyze_with_offline_model(stock_code, stock_name, online_result)
            else:
                offline_result = online_result
            
            # 第三步：整合结果
            final_result = self._integrate_results(online_result, offline_result)
            
            logger.info(f"完成股票 {stock_name}({stock_code}) 的估值指标分析")
            return final_result
            
        except Exception as e:
            logger.error(f"分析股票 {stock_name}({stock_code}) 估值指标时出错: {str(e)}")
            return {
                "success": False,
                "error": str(e),
                "recommended_indicator": None,
                "reasoning": None,
                "valuation_range": None
            }
    
    def _analyze_with_online_model(self, stock_code: str, stock_name: str) -> Dict[str, Any]:
        """
        使用联网大模型进行估值指标分析
        
        Args:
            stock_code: 股票代码
            stock_name: 股票名称
            
        Returns:
            联网模型的分析结果
        """
        try:
            # 构建用户提示词（让联网大模型专注于分析推理，不输出估值区间）
            user_prompt = f"""请深入分析股票代码为{stock_code}、名称为{stock_name}的公司，并判断其更适合使用PE还是PB进行估值。

                                你的分析应超越简单的行业标签，聚焦于该公司的个性化特征。请遵循以下分析框架，提供详细的、基于第一性原理的分析：

                                1.  **盈利质量与可预测性分析**:
                                    * 这家公司的盈利是稳定、持续的，还是波动巨大、难以预测的？
                                    * 其净利润是否真实反映了业务的现金创造能力？
                                    * 是否存在大量非经常性损益影响了其盈利的真实性？

                                2.  **资产价值与商业模式分析**:
                                    * 公司的核心价值更多体现在资产负债表内的有形资产（如设备、土地、金融资产），还是表外的无形资产（如品牌、技术、网络效应）？
                                    * 它的商业模式是“资产驱动型”还是“智力/品牌驱动型”？

                                3.  **周期性与成长性分析**:
                                    * 公司所处行业的周期性强弱如何？它在周期中的位置是怎样的？
                                    * 公司自身的成长性如何，是高于还是低于行业平均水平？

                                4.  **最终决策与依据**:
                                    * 综合以上分析，明确阐述你为什么认为PE或PB是更根本的估值指标。请详细说明你的决策逻辑，将公司的个性化特征与你的结论紧密联系起来。

                                请确保你的分析是客观、专业、有深度的。在本次分析中，请不要提供具体的估值区间，专注于提供选择估值指标的充分理由。"""

            # 调用联网模型
            response = self.online_chatbot.chat(user_prompt, temperature=0.3, max_tokens=2048)
            
            if response.get("success"):
                return {
                    "success": True,
                    "raw_response": response.get("response", ""),
                    "model": "online"
                }
            else:
                logger.error(f"联网模型分析失败: {response.get('error', '未知错误')}")
                return {
                    "success": False,
                    "error": response.get('error', '联网模型分析失败'),
                    "model": "online"
                }
                
        except Exception as e:
            logger.error(f"使用联网模型分析时出错: {str(e)}")
            return {
                "success": False,
                "error": str(e),
                "model": "online"
            }
    
    def _analyze_with_offline_model(self, stock_code: str, stock_name: str, online_result: Dict[str, Any]) -> Dict[str, Any]:
        """
        使用本地GLM模型提取最终的PE/PB推荐
        
        Args:
            stock_code: 股票代码
            stock_name: 股票名称
            online_result: 联网模型的分析结果
            
        Returns:
            本地模型的分析结果
        """
        try:
            # 构建用户提示词（让本地GLM专注于提取最终结果）
            user_prompt = f"""你是一个专注于语义理解和结论提取的AI。你的唯一任务是阅读一段分析报告，理解其核心论点，并判断作者最终推荐的估值指标是 "PE" 还是 "PB"。

                            你的输出必须严格遵守以下规则：
                            * 你的输出**必须且只能是** "PE" 或 "PB"。
                            * 不要添加任何解释、理由或多余的字符。
                            * 如果文本结论确实模棱两可，无法明确判断，**请默认输出 "PE"**。

                            分析内容如下：
                            ---
                            {online_result.get('raw_response', '分析失败')}
                            ---
                            """

            # 调用本地模型
            response = self.offline_chatbot.chat(user_prompt, temperature=0.1, max_tokens=10)
            
            if response.get("success"):
                return {
                    "success": True,
                    "raw_response": response.get("response", "").strip(),
                    "model": "offline"
                }
            else:
                logger.error(f"本地模型分析失败: {response.get('error', '未知错误')}")
                return {
                    "success": False,
                    "error": response.get('error', '本地模型分析失败'),
                    "model": "offline"
                }
                
        except Exception as e:
            logger.error(f"使用本地模型分析时出错: {str(e)}")
            return {
                "success": False,
                "error": str(e),
                "model": "offline"
            }
    
    def _integrate_results(self, online_result: Dict[str, Any], offline_result: Dict[str, Any]) -> Dict[str, Any]:
        """
        整合联网模型和本地模型的结果
        
        Args:
            online_result: 联网模型结果
            offline_result: 本地模型结果
            
        Returns:
            整合后的最终结果
        """
        try:
            # 如果联网模型成功
            if online_result.get("success"):
                # 获取联网模型的分析内容
                online_analysis = online_result.get("raw_response", "")
                
                # 如果本地模型也成功，使用本地模型提取的PE/PB推荐
                if offline_result.get("success"):
                    recommended_indicator = offline_result.get("raw_response", "").strip()
                    
                    # 验证推荐指标是否有效
                    if recommended_indicator in ["PE", "PB"]:
                        return {
                            "success": True,
                            "recommended_indicator": recommended_indicator,
                            "reasoning": online_analysis
                        }
                    else:
                        # 本地模型输出无效，使用联网模型的结果
                        logger.warning(f"本地模型输出无效: {recommended_indicator}")
                        return {
                            "success": True,
                            "recommended_indicator": self._extract_indicator_from_text(online_analysis),
                            "reasoning": online_analysis
                        }
                else:
                    # 只有联网模型成功
                    return {
                        "success": True,
                        "recommended_indicator": self._extract_indicator_from_text(online_analysis),
                        "reasoning": online_analysis
                    }
            else:
                # 联网模型失败
                return {
                    "success": False,
                    "error": online_result.get("error", "分析失败")
                }
                
        except Exception as e:
            logger.error(f"整合结果时出错: {str(e)}")
            return {
                "success": False,
                "error": str(e)
            }
    
    def _extract_indicator_from_text(self, text: str) -> Optional[str]:
        """从文本中提取推荐的估值指标"""
        try:
            import re
            
            # 查找推荐估值指标
            patterns = [
                r'推荐估值指标[：:]\s*(PE|PB)',
                r'应该使用\s*(PE|PB)\s*估值',
                r'选择\s*(PE|PB)\s*作为',
                r'优先选择\s*(PE|PB)'
            ]
            
            for pattern in patterns:
                match = re.search(pattern, text, re.IGNORECASE)
                if match:
                    return match.group(1).upper()
            
            return None
            
        except Exception as e:
            logger.error(f"提取估值指标时出错: {str(e)}")
            return None
    
    def _extract_reasoning_from_text(self, text: str) -> Dict[str, str]:
        """从文本中提取推理过程"""
        try:
            reasoning = {
                "industry_analysis": "",
                "business_model_analysis": "",
                "financial_analysis": "",
                "decision_basis": ""
            }
            
            # 简单的文本提取逻辑
            lines = text.split('\n')
            current_section = None
            
            for line in lines:
                line = line.strip()
                if not line:
                    continue
                    
                if '行业特征分析' in line or '行业分析' in line:
                    current_section = 'industry_analysis'
                elif '商业模式分析' in line or '业务模式分析' in line:
                    current_section = 'business_model_analysis'
                elif '财务特征分析' in line or '财务分析' in line:
                    current_section = 'financial_analysis'
                elif '决策依据' in line or '选择依据' in line:
                    current_section = 'decision_basis'
                elif current_section and line:
                    reasoning[current_section] += line + " "
            
            # 清理空白内容
            for key in reasoning:
                reasoning[key] = reasoning[key].strip()
                
            return reasoning
            
        except Exception as e:
            logger.error(f"提取推理过程时出错: {str(e)}")
            return {
                "industry_analysis": "",
                "business_model_analysis": "",
                "financial_analysis": "",
                "decision_basis": ""
            }
    
    def _extract_valuation_range_from_text(self, text: str) -> Dict[str, Any]:
        """从文本中提取估值区间"""
        try:
            import re
            
            # 查找PE或PB的估值区间
            pe_pattern = r'PE.*?(\d+(?:\.\d+)?)[-~](\d+(?:\.\d+)?)'
            pb_pattern = r'PB.*?(\d+(?:\.\d+)?)[-~](\d+(?:\.\d+)?)'
            
            pe_match = re.search(pe_pattern, text, re.IGNORECASE)
            pb_match = re.search(pb_pattern, text, re.IGNORECASE)
            
            if pe_match:
                return {
                    "type": "PE",
                    "min_value": float(pe_match.group(1)),
                    "max_value": float(pe_match.group(2)),
                    "unit": "倍"
                }
            elif pb_match:
                return {
                    "type": "PB",
                    "min_value": float(pb_match.group(1)),
                    "max_value": float(pb_match.group(2)),
                    "unit": "倍"
                }
            else:
                return {
                    "type": None,
                    "min_value": None,
                    "max_value": None,
                    "unit": "倍"
                }
                
        except Exception as e:
            logger.error(f"提取估值区间时出错: {str(e)}")
            return {
                "type": None,
                "min_value": None,
                "max_value": None,
                "unit": "倍"
            }


def test_valuation_analyzer():
    """测试估值指标分析器"""
    try:
        analyzer = ValuationIndicatorAnalyzer()
        
        # 测试用例
        test_cases = [
            ("000001", "平安银行"),  # 金融业，应该推荐PB
            ("000002", "万科A"),     # 房地产，应该推荐PB
            ("000858", "五粮液"),    # 消费品，应该推荐PE
            ("002415", "海康威视"),  # 科技股，应该推荐PE
        ]
        
        for stock_code, stock_name in test_cases:
            print(f"\n测试股票: {stock_name}({stock_code})")
            result = analyzer.analyze_valuation_indicator(stock_code, stock_name)
            
            if result.get("success"):
                print(f"推荐指标: {result.get('recommended_indicator')}")
                print(f"推理过程: {result.get('reasoning')}")
                print(f"估值区间: {result.get('valuation_range')}")
            else:
                print(f"分析失败: {result.get('error')}")
                
    except Exception as e:
        print(f"测试失败: {str(e)}")


if __name__ == "__main__":
    test_valuation_analyzer() 