"""
Output Formatter
Formats processed data to match SQL output format
"""
import pandas as pd
from typing import Dict, Any


class OutputFormatter:
    """Format processed flow data for API response"""
    
    @staticmethod
    def format_premium(value: float) -> str:
        """Format premium value (M, K, or plain number)"""
        if pd.isna(value) or value is None:
            return None
        
        try:
            abs_val = abs(float(value))
            sign = '-' if float(value) < 0 else ''
            
            if abs_val >= 1e6:
                return f"{sign}{abs_val / 1e6:.2f} M"
            elif abs_val >= 1e3:
                return f"{sign}{int(round(abs_val / 1e3))} K"
            else:
                return f"{sign}{int(round(abs_val))}"
        except (TypeError, ValueError):
            return None
    
    @staticmethod
    def format_symbol_display(row: Dict[str, Any]) -> str:
        """Format symbol display line"""
        direction = row.get('direction', '')
        dir_count = row.get('dir_count', 0) or 0
        symbol = row.get('Symbol') or row.get('symbol_norm', '')
        session_bucket = row.get('session_bucket', '?')
        near_alert_type = row.get('near_alert_type')
        badge_round = row.get('badge_round', '')
        badge_more = row.get('badge_more', '')
        flash = row.get('flash', '')
        premium_num = row.get('premium_num', 0) or 0
        
        # Direction prefix
        if direction == 'BULL':
            prefix = f"({dir_count}🟩)  "
        elif direction == 'BEAR':
            prefix = f"({dir_count}🟥)  "
        else:
            prefix = ""
        
        # Catalyst indicator
        catalyst = " ⚡" if near_alert_type else ""
        
        # Badges
        badges = f" {badge_round}{badge_more}" if (badge_round or badge_more) else ""
        
        # Fire emoji
        if premium_num > 1000000:
            fire = " 🔥"
        elif premium_num > 500000:
            fire = " 💵"
        elif premium_num > 100000:
            fire = " "
        else:
            fire = ""
        
        return f"{prefix}{symbol} · {session_bucket}{catalyst}{badges}{flash}{fire}"
    
    @staticmethod
    def format_tape_align(row: Dict[str, Any]) -> str:
        """Format tape alignment arrow"""
        tape_alignment = row.get('tape_alignment', 0)
        direction = row.get('direction', '')
        
        if tape_alignment == 1:
            return '↗︎' if direction == 'BULL' else '↘︎'
        return ''
    
    @staticmethod
    def format_time(ts_local) -> str:
        """Format time as HH12:MI:SS AM"""
        if pd.isna(ts_local):
            return None
        
        if isinstance(ts_local, str):
            return ts_local
        
        try:
            return ts_local.strftime('%I:%M:%S %p')
        except (AttributeError, ValueError):
            return None
    
    @staticmethod
    def format_final_output(df: pd.DataFrame) -> pd.DataFrame:
        """Format final output to match SQL query format"""
        if df.empty:
            return df
        
        df = df.copy()
        
        # Format dates and times (handle missing columns)
        if 'flow_ts_local' in df.columns:
            df['CreatedDate'] = pd.to_datetime(df['flow_ts_local'], errors='coerce').dt.date
            df['CreatedTime'] = df['flow_ts_local'].apply(OutputFormatter.format_time)
        else:
            df['CreatedDate'] = None
            df['CreatedTime'] = None
        
        # Format symbol display (handle missing columns)
        if all(col in df.columns for col in ['direction', 'dir_count', 'Symbol', 'symbol_norm', 'session_bucket']):
            df['Symbol'] = df.apply(OutputFormatter.format_symbol_display, axis=1)
        elif 'Symbol' in df.columns or 'symbol_norm' in df.columns:
            df['Symbol'] = df.get('Symbol', df.get('symbol_norm', ''))
        
        # Format premiums
        df['NetPremium'] = df.apply(
            lambda row: OutputFormatter.format_premium(
                (row.get('bull_total', 0) or 0) - (row.get('bear_total', 0) or 0)
            ),
            axis=1
        )
        
        df['Premium'] = df.apply(
            lambda row: OutputFormatter.format_premium(row.get('premium_num')),
            axis=1
        )
        
        # Format tape alignment
        df['TapeAlign'] = df.apply(OutputFormatter.format_tape_align, axis=1)
        
        # Rename columns to match SQL output
        column_mapping = {
            'pct_vs_prior_close': 'PctVsPriorClose',
            'pct_vs_rth_open': 'PctVsRthOpen',
            'pct_5m_momo': 'Pct5m',
            'pct_15m_momo': 'Pct15m',
            'near_alert_type': 'NearAlert',
            'Rocket_with_mny': 'Rocket',
        }
        
        # Only rename columns that exist (don't drop Phase 1 columns)
        existing_mapping = {k: v for k, v in column_mapping.items() if k in df.columns}
        df = df.rename(columns=existing_mapping)
        
        # Ensure Phase 1 columns are preserved (don't drop them)
        # Phase 1 columns should remain as-is (signal_tier, checklist_score, etc.)
        
        # Ensure all new institutional analytics columns are preserved:
        # - premium_zscore, premium_percentile_intraday, relative_premium_score
        # - aggression_score, size_concentration_score, repeat_trade_velocity, strike_clustering_score, signal_strength
        # - early_noise_reject, flow_acceleration, time_between_hits, follow_on_ratio, strike_laddering_detected
        # - delta_exposure, gamma_exposure, volatility_intent
        # - net_gamma_exposure_per_symbol, gamma_flip_proximity, dealer_hedge_pressure_score
        # - market_regime, flow_state
        # - confidence_score, institutional_likelihood, dealer_pain_level, expected_move_vs_implied
        
        return df

