"""
智瞰龙虎AI智能评分模块
对龙虎榜上榜股票进行综合评分排名
"""

import pandas as pd
from typing import Dict, List
from collections import Counter


class LonghubangScoring:
    """龙虎榜股票智能评分系统"""
    
    def __init__(self):
        """初始化评分系统"""
        # 顶级游资名单（根据市场知名度和历史战绩）
        self.top_youzi = [
            '赵老哥', '章盟主', '92科比', '瑞鹤仙', '小鳄鱼',
            '养家心法', '欢乐海岸', '古北路', '成都系', '佛山系',
            '方新侠', '乔帮主', '淮海路', '东方财富',
            '国信深圳', '华泰深圳', '中信杭州', '招商深圳'
        ]
        
        # 知名游资（次一级）
        self.famous_youzi = [
            '深股通', '沪股通', '北向资金',
            '中金公司', '中信证券', '国泰君安', '海通证券',
            '广发证券', '华泰证券', '招商证券'
        ]
        
        # 机构关键词
        self.institution_keywords = [
            '机构专用', '机构', '基金', '保险', '社保',
            'QFII', 'RQFII', '券商', '信托'
        ]
        
        print("[智瞰龙虎] 评分系统初始化完成")
    
    def calculate_stock_score(self, stock_data: List[Dict]) -> float:
        """
        计算单个股票的综合评分
        
        Args:
            stock_data: 该股票的所有龙虎榜记录
            
        Returns:
            综合评分 (0-100分)
        """
        if not stock_data:
            return 0.0
        
        # 1. 买入资金含金量评分 (0-30分)
        capital_quality_score = self._calculate_capital_quality(stock_data)
        
        # 2. 净买入额评分 (0-25分)
        net_inflow_score = self._calculate_net_inflow_score(stock_data)
        
        # 3. 卖出压力评分 (0-20分)
        sell_pressure_score = self._calculate_sell_pressure_score(stock_data)
        
        # 4. 机构共振评分 (0-15分)
        institution_score = self._calculate_institution_score(stock_data)
        
        # 5. 其他加分项 (0-10分)
        bonus_score = self._calculate_bonus_score(stock_data)
        
        # 综合评分
        total_score = (
            capital_quality_score +
            net_inflow_score +
            sell_pressure_score +
            institution_score +
            bonus_score
        )
        
        return round(total_score, 1)
    
    def _calculate_capital_quality(self, stock_data: List[Dict]) -> float:
        """
        计算买入资金含金量评分 (0-30分)
        顶级游资加分多，普通游资加分少
        """
        score = 0.0
        max_score = 30.0
        
        buyers = []
        for record in stock_data:
            buy_amount = record.get('买入金额', 0) or record.get('mrje', 0)
            # 确保转换为数值类型
            try:
                buy_amount = float(buy_amount) if buy_amount else 0
            except (ValueError, TypeError):
                buy_amount = 0
            
            if buy_amount > 0:
                youzi_name = record.get('游资名称', '') or record.get('yzmc', '')
                yingye_bu = record.get('营业部', '') or record.get('yyb', '')
                buyers.append({
                    'name': youzi_name,
                    'yingye_bu': yingye_bu,
                    'amount': float(buy_amount)
                })
        
        if not buyers:
            return 0.0
        
        # 顶级游资：每个加8-10分
        top_youzi_count = 0
        for buyer in buyers:
            for top in self.top_youzi:
                if top in buyer['name'] or top in buyer['yingye_bu']:
                    top_youzi_count += 1
                    score += 10.0
                    break
        
        # 知名游资：每个加4-6分
        famous_youzi_count = 0
        for buyer in buyers:
            is_top = any(top in buyer['name'] or top in buyer['yingye_bu'] 
                        for top in self.top_youzi)
            if not is_top:
                for famous in self.famous_youzi:
                    if famous in buyer['name'] or famous in buyer['yingye_bu']:
                        famous_youzi_count += 1
                        score += 5.0
                        break
        
        # 普通游资：每个加1-2分
        ordinary_count = len(buyers) - top_youzi_count - famous_youzi_count
        score += ordinary_count * 1.5
        
        # 限制最高分
        return min(score, max_score)
    
    def _calculate_net_inflow_score(self, stock_data: List[Dict]) -> float:
        """
        计算净买入额评分 (0-25分)
        真金白银越多分数越高
        """
        max_score = 25.0
        
        # 计算总净流入
        total_net_inflow = 0.0
        for record in stock_data:
            net_inflow = record.get('净流入金额', 0) or record.get('jlrje', 0)
            try:
                net_inflow = float(net_inflow) if net_inflow else 0
                total_net_inflow += net_inflow
            except (ValueError, TypeError):
                pass
        
        if total_net_inflow <= 0:
            return 0.0
        
        # 净流入分段评分
        # 1000万以下：0-10分
        # 1000-5000万：10-18分
        # 5000万-1亿：18-22分
        # 1亿以上：22-25分
        net_inflow_wan = total_net_inflow / 10000  # 转换为万元
        
        if net_inflow_wan < 1000:
            score = (net_inflow_wan / 1000) * 10
        elif net_inflow_wan < 5000:
            score = 10 + ((net_inflow_wan - 1000) / 4000) * 8
        elif net_inflow_wan < 10000:
            score = 18 + ((net_inflow_wan - 5000) / 5000) * 4
        else:
            score = 22 + min((net_inflow_wan - 10000) / 10000, 1) * 3
        
        return min(score, max_score)
    
    def _calculate_sell_pressure_score(self, stock_data: List[Dict]) -> float:
        """
        计算卖出压力评分 (0-20分)
        卖出压力越小分数越高
        """
        max_score = 20.0
        
        total_buy = 0.0
        total_sell = 0.0
        
        for record in stock_data:
            buy_amount = record.get('买入金额', 0) or record.get('mrje', 0)
            sell_amount = record.get('卖出金额', 0) or record.get('mcje', 0)
            
            try:
                buy_amount = float(buy_amount) if buy_amount else 0
                total_buy += buy_amount
            except (ValueError, TypeError):
                pass
            
            try:
                sell_amount = float(sell_amount) if sell_amount else 0
                total_sell += sell_amount
            except (ValueError, TypeError):
                pass
        
        if total_buy == 0:
            return 0.0
        
        # 计算卖出比例
        sell_ratio = total_sell / total_buy if total_buy > 0 else 1.0
        
        # 卖出压力评分
        # 卖出比例0-10%：20分
        # 卖出比例10-30%：15-20分
        # 卖出比例30-50%：10-15分
        # 卖出比例50-80%：5-10分
        # 卖出比例80%以上：0-5分
        if sell_ratio < 0.1:
            score = 20.0
        elif sell_ratio < 0.3:
            score = 20.0 - (sell_ratio - 0.1) / 0.2 * 5
        elif sell_ratio < 0.5:
            score = 15.0 - (sell_ratio - 0.3) / 0.2 * 5
        elif sell_ratio < 0.8:
            score = 10.0 - (sell_ratio - 0.5) / 0.3 * 5
        else:
            score = 5.0 - min(sell_ratio - 0.8, 0.2) / 0.2 * 5
        
        return max(0, min(score, max_score))
    
    def _calculate_institution_score(self, stock_data: List[Dict]) -> float:
        """
        计算机构共振评分 (0-15分)
        机构+游资共振最高分
        """
        max_score = 15.0
        
        has_institution = False
        has_youzi = False
        institution_count = 0
        youzi_count = 0
        
        for record in stock_data:
            buy_amount = record.get('买入金额', 0) or record.get('mrje', 0)
            try:
                buy_amount = float(buy_amount) if buy_amount else 0
            except (ValueError, TypeError):
                buy_amount = 0
            
            if buy_amount <= 0:
                continue
            
            youzi_name = record.get('游资名称', '') or record.get('yzmc', '')
            yingye_bu = record.get('营业部', '') or record.get('yyb', '')
            
            # 检查是否是机构
            if any(keyword in youzi_name or keyword in yingye_bu 
                  for keyword in self.institution_keywords):
                has_institution = True
                institution_count += 1
            else:
                has_youzi = True
                youzi_count += 1
        
        # 评分逻辑
        if has_institution and has_youzi:
            # 机构+游资共振：最高分
            score = 15.0
        elif has_institution:
            # 仅机构：8-12分
            score = min(8 + institution_count * 2, 12)
        elif has_youzi:
            # 仅游资：5-10分
            score = min(5 + youzi_count * 1, 10)
        else:
            score = 0.0
        
        return min(score, max_score)
    
    def _calculate_bonus_score(self, stock_data: List[Dict]) -> float:
        """
        计算其他加分项 (0-10分)
        买卖比例、主力集中度、热门概念等
        """
        max_score = 10.0
        score = 0.0
        
        if not stock_data:
            return 0.0
        
        # 1. 主力集中度加分 (0-3分)
        # 如果资金集中在少数几个席位，说明主力信心强
        seat_count = len(stock_data)
        if seat_count == 1:
            score += 3.0
        elif seat_count == 2:
            score += 2.5
        elif seat_count == 3:
            score += 2.0
        elif seat_count <= 5:
            score += 1.5
        else:
            score += 1.0
        
        # 2. 热门概念加分 (0-3分)
        all_concepts = []
        for record in stock_data:
            concepts = record.get('概念', '') or record.get('gl', '')
            if concepts:
                all_concepts.extend([c.strip() for c in str(concepts).split(',')])
        
        hot_keywords = [
            '人工智能', 'AI', 'ChatGPT', '算力', '新能源', '芯片', '半导体',
            '军工', '医药', '消费', '5G', '新材料', '量子', '光伏',
            '储能', '锂电池', '汽车', '游戏', '传媒', '元宇宙'
        ]
        
        concept_score = 0
        for concept in all_concepts:
            if any(keyword in concept for keyword in hot_keywords):
                concept_score += 0.3
        
        score += min(concept_score, 3.0)
        
        # 3. 连续上榜加分 (0-2分)
        # 这里简化处理，如果有多条记录可能表示连续上榜
        if len(stock_data) >= 3:
            score += 2.0
        elif len(stock_data) == 2:
            score += 1.0
        
        # 4. 买卖比例优秀加分 (0-2分)
        total_buy = 0.0
        total_sell = 0.0
        for r in stock_data:
            try:
                buy = float(r.get('买入金额', 0) or r.get('mrje', 0) or 0)
                total_buy += buy
            except (ValueError, TypeError):
                pass
            try:
                sell = float(r.get('卖出金额', 0) or r.get('mcje', 0) or 0)
                total_sell += sell
            except (ValueError, TypeError):
                pass
        
        if total_buy > 0:
            buy_sell_ratio = total_buy / (total_sell + 1)
            if buy_sell_ratio >= 10:
                score += 2.0
            elif buy_sell_ratio >= 5:
                score += 1.5
            elif buy_sell_ratio >= 3:
                score += 1.0
        
        return min(score, max_score)
    
    def score_all_stocks(self, data_list: List[Dict]) -> pd.DataFrame:
        """
        对所有上榜股票进行评分排名
        
        Args:
            data_list: 龙虎榜数据列表
            
        Returns:
            评分排名DataFrame
        """
        if not data_list:
            return pd.DataFrame()
        
        # 按股票代码分组
        stocks_dict = {}
        for record in data_list:
            code = record.get('股票代码') or record.get('gpdm')
            name = record.get('股票名称') or record.get('gpmc')
            
            if not code:
                continue
            
            if code not in stocks_dict:
                stocks_dict[code] = {
                    'code': code,
                    'name': name,
                    'records': []
                }
            
            stocks_dict[code]['records'].append(record)
        
        # 计算每只股票的评分
        results = []
        for code, stock_info in stocks_dict.items():
            records = stock_info['records']
            
            # 计算各维度评分
            capital_quality = self._calculate_capital_quality(records)
            net_inflow = self._calculate_net_inflow_score(records)
            sell_pressure = self._calculate_sell_pressure_score(records)
            institution = self._calculate_institution_score(records)
            bonus = self._calculate_bonus_score(records)
            
            total_score = capital_quality + net_inflow + sell_pressure + institution + bonus
            
            # 计算实际数据（安全转换）
            total_buy = 0.0
            total_sell = 0.0
            total_net = 0.0
            for r in records:
                try:
                    buy = float(r.get('买入金额', 0) or r.get('mrje', 0) or 0)
                    total_buy += buy
                except (ValueError, TypeError):
                    pass
                try:
                    sell = float(r.get('卖出金额', 0) or r.get('mcje', 0) or 0)
                    total_sell += sell
                except (ValueError, TypeError):
                    pass
                try:
                    net = float(r.get('净流入金额', 0) or r.get('jlrje', 0) or 0)
                    total_net += net
                except (ValueError, TypeError):
                    pass
            
            # 统计买入席位数（安全比较）
            buy_seats = 0
            for r in records:
                try:
                    buy = float(r.get('买入金额', 0) or r.get('mrje', 0) or 0)
                    if buy > 0:
                        buy_seats += 1
                except (ValueError, TypeError):
                    pass
            
            # 统计机构数量
            institution_count = sum(1 for r in records 
                                  if any(kw in (r.get('游资名称', '') or r.get('yzmc', '')) or 
                                        kw in (r.get('营业部', '') or r.get('yyb', ''))
                                        for kw in self.institution_keywords))
            
            # 获取概念
            concepts_list = []
            for r in records:
                concepts = r.get('概念', '') or r.get('gl', '')
                if concepts:
                    concepts_list.extend([c.strip() for c in str(concepts).split(',')])
            
            top_concepts = Counter(concepts_list).most_common(3)
            concept_str = ','.join([c[0] for c in top_concepts]) if top_concepts else ''
            
            # 判断机构参与
            has_institution = institution_count > 0
            
            results.append({
                '排名': 0,  # 稍后填充
                '股票名称': stock_info['name'],
                '股票代码': code,
                '综合评分': round(total_score, 1),
                '资金含金量': round(capital_quality, 0),
                '净买入额': round(net_inflow, 0),
                '卖出压力': round(sell_pressure, 0),
                '机构共振': round(institution, 0),
                '加分项': round(bonus, 0),
                '顶级游资': self._count_top_youzi(records),
                '买方数': buy_seats,
                '机构参与': '✅' if has_institution else '❌',
                '净流入': round(total_net, 2)
            })
        
        # 转换为DataFrame并排序
        df = pd.DataFrame(results)
        if df.empty:
            return df
        
        df = df.sort_values('综合评分', ascending=False).reset_index(drop=True)
        df['排名'] = range(1, len(df) + 1)
        
        # 添加奖牌
        if len(df) >= 1:
            df.loc[0, '排名'] = '🥇 1'
        if len(df) >= 2:
            df.loc[1, '排名'] = '🥈 2'
        if len(df) >= 3:
            df.loc[2, '排名'] = '🥉 3'
        
        return df
    
    def _count_top_youzi(self, records: List[Dict]) -> int:
        """统计顶级游资数量"""
        count = 0
        for record in records:
            buy_amount = record.get('买入金额', 0) or record.get('mrje', 0)
            try:
                buy_amount = float(buy_amount) if buy_amount else 0
            except (ValueError, TypeError):
                buy_amount = 0
            
            if buy_amount <= 0:
                continue
            
            youzi_name = record.get('游资名称', '') or record.get('yzmc', '')
            yingye_bu = record.get('营业部', '') or record.get('yyb', '')
            
            if any(top in youzi_name or top in yingye_bu for top in self.top_youzi):
                count += 1
        
        return count
    
    def get_score_explanation(self) -> str:
        """获取评分维度说明"""
        explanation = """
        【AI智能评分维度说明】
        
        📊 总分100分，由5个维度组成：
        
        1️⃣ 买入资金含金量 (0-30分)
           - 顶级游资（赵老哥、章盟主等）：每个+10分
           - 知名游资（深股通、中信等）：每个+5分
           - 普通游资：每个+1.5分
           
        2️⃣ 净买入额评分 (0-25分)
           - 净流入1000万以下：0-10分
           - 净流入1000-5000万：10-18分
           - 净流入5000万-1亿：18-22分
           - 净流入1亿以上：22-25分
           
        3️⃣ 卖出压力评分 (0-20分)
           - 卖出比例0-10%：20分（压力极小）
           - 卖出比例10-30%：15-20分（压力较小）
           - 卖出比例30-50%：10-15分（压力中等）
           - 卖出比例50-80%：5-10分（压力较大）
           - 卖出比例80%以上：0-5分（压力极大）
           
        4️⃣ 机构共振评分 (0-15分)
           - 机构+游资共振：15分（最强信号）
           - 仅机构买入：8-12分
           - 仅游资买入：5-10分
           
        5️⃣ 其他加分项 (0-10分)
           - 主力集中度：席位越少越集中，+1-3分
           - 热门概念：AI、新能源、芯片等，+0-3分
           - 连续上榜：连续多日上榜，+0-2分
           - 买卖比例优秀：买入远大于卖出，+0-2分
        
        💡 评分越高，表示该股票受到资金青睐程度越高，
           但仍需结合市场环境、技术面等因素综合判断！
        """
        return explanation


# 测试函数
if __name__ == "__main__":
    print("=" * 60)
    print("测试智瞰龙虎评分系统")
    print("=" * 60)
    
    # 创建测试数据
    test_data = [
        {
            '股票代码': '001337',
            '股票名称': '四川黄金',
            '游资名称': '92科比',
            '营业部': '兴业证券股份有限公司南京天元东路证券营业部',
            '买入金额': 14470401,
            '卖出金额': 15080,
            '净流入金额': 14455321,
            '概念': '贵金属,黄金概念,次新股'
        },
        {
            '股票代码': '001337',
            '股票名称': '四川黄金',
            '游资名称': '赵老哥',
            '营业部': '某证券公司',
            '买入金额': 10000000,
            '卖出金额': 0,
            '净流入金额': 10000000,
            '概念': '贵金属,黄金概念'
        }
    ]
    
    scoring = LonghubangScoring()
    
    # 测试评分
    df_result = scoring.score_all_stocks(test_data)
    
    print("\n评分结果：")
    print(df_result)
    
    print("\n" + scoring.get_score_explanation())

