"""
Economy Processor - Handles leetify economic data

Responsibilities:
- Parse bron_equipment (equipment lists)
- Parse player_bron_crash (starting money)
- Calculate equipment_value
- Write to fact_round_player_economy and update fact_rounds
"""

import sqlite3
import json
import logging
import uuid

logger = logging.getLogger(__name__)


class EconomyProcessor:
    @staticmethod
    def process_classic(match_data, conn: sqlite3.Connection) -> bool:
        """
        Process classic economy data (extracted from round_list equiped)
        """
        try:
            cursor = conn.cursor()
            
            for r in match_data.rounds:
                if not r.economies:
                    continue
                    
                for eco in r.economies:
                    if eco.side not in ['CT', 'T']:
                        # Skip rounds where side cannot be determined (avoids CHECK constraint failure)
                        continue
                        
                    cursor.execute('''
                        INSERT OR REPLACE INTO fact_round_player_economy (
                            match_id, round_num, steam_id_64, side, start_money,
                            equipment_value, main_weapon, has_helmet, has_defuser,
                            has_zeus, round_performance_score, data_source_type
                        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                    ''', (
                        match_data.match_id, r.round_num, eco.steam_id_64, eco.side, eco.start_money,
                        eco.equipment_value, eco.main_weapon, eco.has_helmet, eco.has_defuser,
                        eco.has_zeus, eco.round_performance_score, 'classic'
                    ))
            
            return True
        except Exception as e:
            logger.error(f"Error processing classic economy for match {match_data.match_id}: {e}")
            import traceback
            traceback.print_exc()
            return False

    @staticmethod
    def process_leetify(match_data, conn: sqlite3.Connection) -> bool:
        """
        Process leetify economy and round 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()
            
            for r in round_stats:
                round_num = r.get('round', 0)
                
                # Extract round-level data
                ct_money_start = r.get('ct_money_group', 0)
                t_money_start = r.get('t_money_group', 0)
                win_reason = r.get('win_reason', 0)
                
                # Get timestamps
                begin_ts = r.get('begin_ts', '')
                end_ts = r.get('end_ts', '')
                
                # Get sfui_event for scores
                sfui = r.get('sfui_event', {})
                ct_score = sfui.get('score_ct', 0)
                t_score = sfui.get('score_t', 0)
                
                # Determine winner_side based on show_event
                show_events = r.get('show_event', [])
                winner_side = 'None'
                duration = 0.0
                
                if show_events:
                    last_event = show_events[-1]
                    # Check if there's a win_reason in the last event
                    if last_event.get('win_reason'):
                        win_reason = last_event.get('win_reason', 0)
                        # Map win_reason to winner_side
                        # Typical mappings: 1=T_Win, 2=CT_Win, etc.
                        winner_side = _map_win_reason_to_side(win_reason)
                    
                    # Calculate duration from event timestamps
                    if 'ts' in last_event:
                        duration = float(last_event.get('ts', 0))
                
                # 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, ct_money_start, t_money_start,
                        begin_ts, end_ts, data_source_type
                    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                ''', (
                    match_data.match_id, round_num, winner_side, win_reason,
                    _map_win_reason_desc(win_reason), duration, ct_score, t_score,
                    ct_money_start, t_money_start, begin_ts, end_ts, 'leetify'
                ))
                
                # Process economy data
                bron_equipment = r.get('bron_equipment', {})
                player_t_score = r.get('player_t_score', {})
                player_ct_score = r.get('player_ct_score', {})
                player_bron_crash = r.get('player_bron_crash', {})
                
                # Build side mapping
                side_scores = {}
                for sid, val in player_t_score.items():
                    side_scores[str(sid)] = ("T", float(val) if val is not None else 0.0)
                for sid, val in player_ct_score.items():
                    side_scores[str(sid)] = ("CT", float(val) if val is not None else 0.0)
                
                # Process each player's economy
                for sid in set(list(side_scores.keys()) + [str(k) for k in bron_equipment.keys()]):
                    if sid not in side_scores:
                        continue
                    
                    side, perf_score = side_scores[sid]
                    items = bron_equipment.get(sid) or bron_equipment.get(str(sid)) or []
                    
                    start_money = _pick_money(items)
                    equipment_value = player_bron_crash.get(sid) or player_bron_crash.get(str(sid))
                    equipment_value = int(equipment_value) if equipment_value is not None else 0
                    
                    main_weapon = _pick_main_weapon(items)
                    has_helmet = _has_item_type(items, ['weapon_vest', 'item_assaultsuit', 'item_kevlar'])
                    has_defuser = _has_item_type(items, ['item_defuser'])
                    has_zeus = _has_item_type(items, ['weapon_taser'])
                    
                    cursor.execute('''
                        INSERT OR REPLACE INTO fact_round_player_economy (
                            match_id, round_num, steam_id_64, side, start_money,
                            equipment_value, main_weapon, has_helmet, has_defuser,
                            has_zeus, round_performance_score, data_source_type
                        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                    ''', (
                        match_data.match_id, round_num, sid, side, start_money,
                        equipment_value, main_weapon, has_helmet, has_defuser,
                        has_zeus, perf_score, 'leetify'
                    ))
            
            logger.debug(f"Processed {len(round_stats)} leetify rounds for match {match_data.match_id}")
            return True
            
        except Exception as e:
            logger.error(f"Error processing leetify economy for match {match_data.match_id}: {e}")
            import traceback
            traceback.print_exc()
            return False


def _pick_main_weapon(items):
    """Extract main weapon from equipment list"""
    if not isinstance(items, list):
        return ""
    
    ignore = {
        "weapon_knife", "weapon_knife_t", "weapon_knife_gg", "weapon_knife_ct",
        "weapon_c4", "weapon_flashbang", "weapon_hegrenade", "weapon_smokegrenade",
        "weapon_molotov", "weapon_incgrenade", "weapon_decoy"
    }
    
    # First pass: ignore utility
    for it in items:
        if not isinstance(it, dict):
            continue
        name = it.get('WeaponName')
        if name and name not in ignore:
            return name
    
    # Second pass: any weapon
    for it in items:
        if not isinstance(it, dict):
            continue
        name = it.get('WeaponName')
        if name:
            return name
    
    return ""


def _pick_money(items):
    """Extract starting money from equipment list"""
    if not isinstance(items, list):
        return 0
    
    vals = []
    for it in items:
        if isinstance(it, dict) and it.get('Money') is not None:
            vals.append(it.get('Money'))
    
    return int(max(vals)) if vals else 0


def _has_item_type(items, keywords):
    """Check if equipment list contains item matching keywords"""
    if not isinstance(items, list):
        return False
    
    for it in items:
        if not isinstance(it, dict):
            continue
        name = it.get('WeaponName', '')
        if any(kw in name for kw in keywords):
            return True
    
    return False


def _map_win_reason_to_side(win_reason):
    """Map win_reason integer to winner_side"""
    # Common mappings from CS:GO/CS2:
    # 1 = Target_Bombed (T wins)
    # 2 = Bomb_Defused (CT wins)
    # 7 = CTs_Win (CT eliminates T)
    # 8 = Terrorists_Win (T eliminates CT)
    # 9 = Target_Saved (CT wins, time runs out)
    # etc.
    t_win_reasons = {1, 8, 12, 17}
    ct_win_reasons = {2, 7, 9, 11}
    
    if win_reason in t_win_reasons:
        return 'T'
    elif win_reason in ct_win_reasons:
        return 'CT'
    else:
        return 'None'


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