"""航空公司情感分析数据预处理模块"""

import pandas as pd
from pathlib import Path
from typing import Tuple, Dict, List
import re


def validate_dataframe(df: pd.DataFrame) -> pd.DataFrame:
    """简化数据验证函数"""
    # 检查必需列是否存在
    required_columns = ['tweet_id', 'airline_sentiment', 'airline_sentiment_confidence', 
                       'negativereason', 'airline', 'text', 'tweet_created']
    
    missing_columns = [col for col in required_columns if col not in df.columns]
    if missing_columns:
        raise ValueError(f"数据缺失必需列: {missing_columns}")
    
    # 验证airline_sentiment值
    valid_sentiments = ["positive", "neutral", "negative"]
    invalid_sentiments = df[~df['airline_sentiment'].isin(valid_sentiments)]['airline_sentiment'].unique()
    if len(invalid_sentiments) > 0:
        print(f"警告: 发现无效的情感值: {invalid_sentiments}")
    
    # 验证置信度范围
    invalid_confidence = df[(df['airline_sentiment_confidence'] < 0) | (df['airline_sentiment_confidence'] > 1)]
    if len(invalid_confidence) > 0:
        print(f"警告: 发现置信度超出范围 [0,1] 的数据行")
    
    return df


class DataProcessor:
    """数据预处理类"""
    
    def __init__(self, data_path: str):
        self.data_path = Path(data_path)
        self.abb_dict = self._load_abbreviation_dict()
    
    def _load_abbreviation_dict(self) -> Dict[str, str]:
        """加载缩写词典"""
        return {
            'pls': 'please', 'thx': 'thanks', 'ty': 'thank you',
            'u': 'you', 'r': 'are', 'ur': 'your', 'btw': 'by the way',
            'asap': 'as soon as possible', 'fyi': 'for your information',
            'imo': 'in my opinion', 'lol': 'laughing out loud',
            'omg': 'oh my god', 'idk': 'i don\'t know', 'tbh': 'to be honest',
            'afaik': 'as far as i know', 'brb': 'be right back'
        }
    
    def load_data(self) -> pd.DataFrame:
        """加载原始数据"""
        df = pd.read_csv(self.data_path)
        
        # 数据验证
        validated_df = validate_dataframe(df)
        return validated_df
    
    def preprocess_text(self, text: str) -> str:
        """文本预处理 - 克制清洗策略"""
        if pd.isna(text):
            return ""
        
        # 基础清洗：小写化、去除多余空格
        text = str(text).lower().strip()
        text = re.sub(r'\s+', ' ', text)
        
        # 删除表情符号（减少噪声）
        text = re.sub(r'[\U00010000-\U0010ffff]', '', text)  # 删除emoji
        
        # 保留@提及、#标签、URL链接（重要上下文）
        # 不删除这些社交媒体特征
        
        # 缩写/俚语词典映射
        words = text.split()
        processed_words = []
        for word in words:
            # 处理常见缩写
            processed_word = self.abb_dict.get(word, word)
            # 添加注释：在原始词后添加注释
            if word in self.abb_dict and word != processed_word:
                processed_words.append(f"{word}({processed_word})")
            else:
                processed_words.append(processed_word)
        
        return ' '.join(processed_words)
    
    def extract_features(self, df: pd.DataFrame) -> pd.DataFrame:
        """提取特征 - 增强特征工程"""
        df_processed = df.copy()
        
        # 文本预处理
        df_processed['cleaned_text'] = df_processed['text'].apply(self.preprocess_text)
        
        # 文本统计特征
        df_processed['text_length'] = df_processed['cleaned_text'].str.len()
        df_processed['word_count'] = df_processed['cleaned_text'].str.split().str.len()
        df_processed['punctuation_ratio'] = df_processed['cleaned_text'].str.count(r'[!?.,;:]') / (df_processed['text_length'] + 1)
        df_processed['uppercase_ratio'] = df_processed['text'].str.count(r'[A-Z]') / (df_processed['text_length'] + 1)
        
        # 社交媒体特征
        df_processed['mention_count'] = df_processed['text'].str.count(r'@\\w+')
        df_processed['hashtag_count'] = df_processed['text'].str.count(r'#\\w+')
        df_processed['url_count'] = df_processed['text'].str.count(r'http[s]?://')
        df_processed['has_mention'] = (df_processed['mention_count'] > 0).astype(int)
        df_processed['has_hashtag'] = (df_processed['hashtag_count'] > 0).astype(int)
        df_processed['has_url'] = (df_processed['url_count'] > 0).astype(int)
        
        # 负面情感关键词检测（增强负面识别）
        negative_keywords = [
            'terrible', 'awful', 'horrible', 'bad', 'worst', 'disappointing',
            'disgusting', 'hate', 'angry', 'frustrated', 'annoying', 'poor',
            'sucks', 'terrible', 'awful', 'horrible', 'bad', 'worst',
            'delay', 'cancelled', 'lost', 'missing', 'broken', 'damaged'
        ]
        
        def count_negative_words(text):
            if pd.isna(text):
                return 0
            text_lower = str(text).lower()
            return sum(1 for word in negative_keywords if word in text_lower)
        
        df_processed['negative_word_count'] = df_processed['cleaned_text'].apply(count_negative_words)
        df_processed['has_negative_words'] = (df_processed['negative_word_count'] > 0).astype(int)
        
        # 感叹号数量（强烈情感指标）
        df_processed['exclamation_count'] = df_processed['text'].str.count(r'!')
        df_processed['has_exclamation'] = (df_processed['exclamation_count'] > 0).astype(int)
        
        # 结构化特征
        # 航空公司（one-hot编码准备）
        df_processed['airline_encoded'] = df_processed['airline'].astype('category').cat.codes
        
        # 负面原因（多标签特征准备）
        df_processed['has_negative_reason'] = (~df_processed['negativereason'].isna()).astype(int)
        
        # 时间特征
        df_processed['tweet_created'] = pd.to_datetime(df_processed['tweet_created'])
        df_processed['hour'] = df_processed['tweet_created'].dt.hour
        df_processed['day_of_week'] = df_processed['tweet_created'].dt.dayofweek
        df_processed['is_weekend'] = (df_processed['day_of_week'] >= 5).astype(int)
        
        return df_processed
    
    def prepare_training_data(self, df: pd.DataFrame) -> Tuple[pd.DataFrame, pd.Series]:
        """准备训练数据"""
        df_features = self.extract_features(df)
        
        # 选择特征列
        feature_cols = [
            'text_length', 'word_count', 'punctuation_ratio', 'uppercase_ratio',
            'mention_count', 'hashtag_count', 'url_count',
            'has_mention', 'has_hashtag', 'has_url',
            'airline_encoded', 'has_negative_reason',
            'hour', 'day_of_week', 'is_weekend', 'airline_sentiment_confidence'
        ]
        
        X = df_features[feature_cols]
        y = df_features['airline_sentiment']
        
        return X, y


def get_feature_columns() -> Tuple[List[str], List[str]]:
    """获取特征列列表"""
    numeric_features = [
        'text_length', 'word_count', 'punctuation_ratio', 'uppercase_ratio',
        'mention_count', 'hashtag_count', 'url_count',
        'airline_encoded', 'has_negative_reason',
        'hour', 'day_of_week', 'is_weekend', 'airline_sentiment_confidence',
        'negative_word_count', 'exclamation_count'  # 新增负面情感特征
    ]
    categorical_features = ['has_mention', 'has_hashtag', 'has_url', 'has_negative_words', 'has_exclamation']
    
    return numeric_features, categorical_features