"""
Event Processor - Handles kill and bomb events

Responsibilities:
- Process leetify show_event data (kills with score impacts)
- Process classic all_kill and c4_event data
- Generate unique event_ids
- Store twin probability changes (leetify only)
- Handle bomb plant/defuse events
"""

import sqlite3
import json
import logging
import uuid

logger = logging.getLogger(__name__)


class EventProcessor:
    @staticmethod
    def process_leetify_events(match_data, conn: sqlite3.Connection) -> bool:
        """
        Process leetify event data
        
        Args:
            match_data: MatchData object with leetify_data parsed
            conn: L2 database connection
            
        Returns:
            bool: True if successful
        """
        try:
            if not hasattr(match_data, 'data_leetify') or not match_data.data_leetify:
                return True
            
            leetify_data = match_data.data_leetify.get('leetify_data', {})
            round_stats = leetify_data.get('round_stat', [])
            
            if not round_stats:
                return True
            
            cursor = conn.cursor()
            event_count = 0
            
            for r in round_stats:
                round_num = r.get('round', 0)
                show_events = r.get('show_event', [])
                
                for evt in show_events:
                    event_type_code = evt.get('event_type', 0)
                    
                    # event_type: 3=kill, others for bomb/etc
                    if event_type_code == 3 and evt.get('kill_event'):
                        # Process kill event
                        k = evt['kill_event']
                        
                        event_id = str(uuid.uuid4())
                        event_time = evt.get('ts', 0)
                        
                        attacker_steam_id = str(k.get('Killer', ''))
                        victim_steam_id = str(k.get('Victim', ''))
                        weapon = k.get('WeaponName', '')
                        
                        is_headshot = bool(k.get('Headshot', False))
                        is_wallbang = bool(k.get('Penetrated', False))
                        is_blind = bool(k.get('AttackerBlind', False))
                        is_through_smoke = bool(k.get('ThroughSmoke', False))
                        is_noscope = bool(k.get('NoScope', False))
                        
                        # Extract assist info
                        assister_steam_id = None
                        flash_assist_steam_id = None
                        trade_killer_steam_id = None
                        
                        if evt.get('assist_killer_score_change'):
                            assister_steam_id = str(list(evt['assist_killer_score_change'].keys())[0])
                        
                        if evt.get('flash_assist_killer_score_change'):
                            flash_assist_steam_id = str(list(evt['flash_assist_killer_score_change'].keys())[0])
                        
                        if evt.get('trade_score_change'):
                            trade_killer_steam_id = str(list(evt['trade_score_change'].keys())[0])
                        
                        # Extract score changes
                        score_change_attacker = 0.0
                        score_change_victim = 0.0
                        
                        if evt.get('killer_score_change'):
                            vals = list(evt['killer_score_change'].values())
                            if vals and isinstance(vals[0], dict):
                                score_change_attacker = float(vals[0].get('score', 0))
                        
                        if evt.get('victim_score_change'):
                            vals = list(evt['victim_score_change'].values())
                            if vals and isinstance(vals[0], dict):
                                score_change_victim = float(vals[0].get('score', 0))
                        
                        # Extract twin (team win probability) changes
                        twin = evt.get('twin', 0.0)
                        c_twin = evt.get('c_twin', 0.0)
                        twin_change = evt.get('twin_change', 0.0)
                        c_twin_change = evt.get('c_twin_change', 0.0)
                        
                        cursor.execute('''
                            INSERT OR REPLACE INTO fact_round_events (
                                event_id, match_id, round_num, event_type, event_time,
                                attacker_steam_id, victim_steam_id, assister_steam_id,
                                flash_assist_steam_id, trade_killer_steam_id, weapon,
                                is_headshot, is_wallbang, is_blind, is_through_smoke,
                                is_noscope, score_change_attacker, score_change_victim,
                                twin, c_twin, twin_change, c_twin_change, data_source_type
                            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                        ''', (
                            event_id, match_data.match_id, round_num, 'kill', event_time,
                            attacker_steam_id, victim_steam_id, assister_steam_id,
                            flash_assist_steam_id, trade_killer_steam_id, weapon,
                            is_headshot, is_wallbang, is_blind, is_through_smoke,
                            is_noscope, score_change_attacker, score_change_victim,
                            twin, c_twin, twin_change, c_twin_change, 'leetify'
                        ))
                        
                        event_count += 1
            
            logger.debug(f"Processed {event_count} leetify events for match {match_data.match_id}")
            return True
            
        except Exception as e:
            logger.error(f"Error processing leetify events for match {match_data.match_id}: {e}")
            import traceback
            traceback.print_exc()
            return False
    
    @staticmethod
    def process_classic_events(match_data, conn: sqlite3.Connection) -> bool:
        """
        Process classic event data (all_kill, c4_event)
        
        Args:
            match_data: MatchData object with round_list parsed
            conn: L2 database connection
            
        Returns:
            bool: True if successful
        """
        try:
            if not hasattr(match_data, 'data_round_list') or not match_data.data_round_list:
                return True
            
            round_list = match_data.data_round_list.get('round_list', [])
            
            if not round_list:
                return True
            
            cursor = conn.cursor()
            event_count = 0
            
            for idx, rd in enumerate(round_list, start=1):
                round_num = idx
                
                # Extract round basic info for fact_rounds
                current_score = rd.get('current_score', {})
                ct_score = current_score.get('ct', 0)
                t_score = current_score.get('t', 0)
                win_type = current_score.get('type', 0)
                pasttime = current_score.get('pasttime', 0)
                final_round_time = current_score.get('final_round_time', 0)
                
                # Determine winner_side from win_type
                winner_side = _map_win_type_to_side(win_type)
                
                # Insert/update fact_rounds
                cursor.execute('''
                    INSERT OR REPLACE INTO fact_rounds (
                        match_id, round_num, winner_side, win_reason, win_reason_desc,
                        duration, ct_score, t_score, end_time_stamp, final_round_time,
                        pasttime, data_source_type
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                ''', (
                    match_data.match_id, round_num, winner_side, win_type,
                    _map_win_type_desc(win_type), float(pasttime), ct_score, t_score,
                    '', final_round_time, pasttime, 'classic'
                ))
                
                # Process kill events
                all_kill = rd.get('all_kill', [])
                for kill in all_kill:
                    event_id = str(uuid.uuid4())
                    event_time = kill.get('pasttime', 0)
                    
                    attacker = kill.get('attacker', {})
                    victim = kill.get('victim', {})
                    
                    attacker_steam_id = str(attacker.get('steamid_64', ''))
                    victim_steam_id = str(victim.get('steamid_64', ''))
                    weapon = kill.get('weapon', '')
                    
                    is_headshot = bool(kill.get('headshot', False))
                    is_wallbang = bool(kill.get('penetrated', False))
                    is_blind = bool(kill.get('attackerblind', False))
                    is_through_smoke = bool(kill.get('throughsmoke', False))
                    is_noscope = bool(kill.get('noscope', False))
                    
                    # Classic has spatial data - will be filled by spatial_processor
                    # But we still need to insert the event
                    
                    cursor.execute('''
                        INSERT OR REPLACE INTO fact_round_events (
                            event_id, match_id, round_num, event_type, event_time,
                            attacker_steam_id, victim_steam_id, weapon, is_headshot,
                            is_wallbang, is_blind, is_through_smoke, is_noscope,
                            data_source_type
                        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                    ''', (
                        event_id, match_data.match_id, round_num, 'kill', event_time,
                        attacker_steam_id, victim_steam_id, weapon, is_headshot,
                        is_wallbang, is_blind, is_through_smoke, is_noscope, 'classic'
                    ))
                    
                    event_count += 1
                
                # Process bomb events
                c4_events = rd.get('c4_event', [])
                for c4 in c4_events:
                    event_id = str(uuid.uuid4())
                    event_name = c4.get('event_name', '')
                    event_time = c4.get('pasttime', 0)
                    steam_id = str(c4.get('steamid_64', ''))
                    
                    # Map event_name to event_type
                    if 'plant' in event_name.lower():
                        event_type = 'bomb_plant'
                        attacker_steam_id = steam_id
                        victim_steam_id = None
                    elif 'defuse' in event_name.lower():
                        event_type = 'bomb_defuse'
                        attacker_steam_id = steam_id
                        victim_steam_id = None
                    else:
                        event_type = 'unknown'
                        attacker_steam_id = steam_id
                        victim_steam_id = None
                    
                    cursor.execute('''
                        INSERT OR REPLACE INTO fact_round_events (
                            event_id, match_id, round_num, event_type, event_time,
                            attacker_steam_id, victim_steam_id, data_source_type
                        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
                    ''', (
                        event_id, match_data.match_id, round_num, event_type,
                        event_time, attacker_steam_id, victim_steam_id, 'classic'
                    ))
                    
                    event_count += 1
            
            logger.debug(f"Processed {event_count} classic events for match {match_data.match_id}")
            return True
            
        except Exception as e:
            logger.error(f"Error processing classic events for match {match_data.match_id}: {e}")
            import traceback
            traceback.print_exc()
            return False


def _map_win_type_to_side(win_type):
    """Map win_type to winner_side for classic data"""
    # Based on CS:GO win types
    t_win_types = {1, 8, 12, 17}
    ct_win_types = {2, 7, 9, 11}
    
    if win_type in t_win_types:
        return 'T'
    elif win_type in ct_win_types:
        return 'CT'
    else:
        return 'None'


def _map_win_type_desc(win_type):
    """Map win_type to description"""
    type_map = {
        0: 'None',
        1: 'TargetBombed',
        2: 'BombDefused',
        7: 'CTsWin',
        8: 'TerroristsWin',
        9: 'TargetSaved',
        11: 'CTSurrender',
        12: 'TSurrender',
        17: 'TerroristsPlanted'
    }
    return type_map.get(win_type, f'Unknown_{win_type}')
