import pandas as pd

# Gen 3 AI Type Interaction List
TYPE_INTERACTIONS = [
    ('NORMAL', 'ROCK', 0.5), ('NORMAL', 'STEEL', 0.5),
    ('FIRE', 'FIRE', 0.5), ('FIRE', 'WATER', 0.5), ('FIRE', 'GRASS', 2.0), ('FIRE', 'ICE', 2.0), ('FIRE', 'BUG', 2.0), ('FIRE', 'ROCK', 0.5), ('FIRE', 'DRAGON', 0.5), ('FIRE', 'STEEL', 2.0),
    ('WATER', 'FIRE', 2.0), ('WATER', 'WATER', 0.5), ('WATER', 'GRASS', 0.5), ('WATER', 'GROUND', 2.0), ('WATER', 'ROCK', 2.0), ('WATER', 'DRAGON', 0.5),
    ('ELECTRIC', 'WATER', 2.0), ('ELECTRIC', 'ELECTRIC', 0.5), ('ELECTRIC', 'GRASS', 0.5), ('ELECTRIC', 'GROUND', 0.0), ('ELECTRIC', 'FLYING', 2.0), ('ELECTRIC', 'DRAGON', 0.5),
    ('GRASS', 'FIRE', 0.5), ('GRASS', 'WATER', 2.0), ('GRASS', 'GRASS', 0.5), ('GRASS', 'POISON', 0.5), ('GRASS', 'GROUND', 2.0), ('GRASS', 'FLYING', 0.5), ('GRASS', 'BUG', 0.5), ('GRASS', 'ROCK', 2.0), ('GRASS', 'DRAGON', 0.5), ('GRASS', 'STEEL', 0.5),
    ('ICE', 'WATER', 0.5), ('ICE', 'GRASS', 2.0), ('ICE', 'ICE', 0.5), ('ICE', 'GROUND', 2.0), ('ICE', 'FLYING', 2.0), ('ICE', 'DRAGON', 2.0), ('ICE', 'STEEL', 0.5), ('ICE', 'FIRE', 0.5),
    ('FIGHTING', 'NORMAL', 2.0), ('FIGHTING', 'ICE', 2.0), ('FIGHTING', 'POISON', 0.5), ('FIGHTING', 'FLYING', 0.5), ('FIGHTING', 'PSYCHIC', 0.5), ('FIGHTING', 'BUG', 0.5), ('FIGHTING', 'ROCK', 2.0), ('FIGHTING', 'DARK', 2.0), ('FIGHTING', 'STEEL', 2.0),
    ('POISON', 'GRASS', 2.0), ('POISON', 'POISON', 0.5), ('POISON', 'GROUND', 0.5), ('POISON', 'ROCK', 0.5), ('POISON', 'GHOST', 0.5), ('POISON', 'STEEL', 0.0),
    ('GROUND', 'FIRE', 2.0), ('GROUND', 'ELECTRIC', 2.0), ('GROUND', 'GRASS', 0.5), ('GROUND', 'POISON', 2.0), ('GROUND', 'FLYING', 0.0), ('GROUND', 'BUG', 0.5), ('GROUND', 'ROCK', 2.0), ('GROUND', 'STEEL', 2.0),
    ('FLYING', 'ELECTRIC', 0.5), ('FLYING', 'GRASS', 2.0), ('FLYING', 'FIGHTING', 2.0), ('FLYING', 'BUG', 2.0), ('FLYING', 'ROCK', 0.5), ('FLYING', 'STEEL', 0.5),
    ('PSYCHIC', 'FIGHTING', 2.0), ('PSYCHIC', 'POISON', 2.0), ('PSYCHIC', 'PSYCHIC', 0.5), ('PSYCHIC', 'DARK', 0.0), ('PSYCHIC', 'STEEL', 0.5),
    ('BUG', 'FIRE', 0.5), ('BUG', 'GRASS', 2.0), ('BUG', 'FIGHTING', 0.5), ('BUG', 'POISON', 0.5), ('BUG', 'FLYING', 0.5), ('BUG', 'PSYCHIC', 2.0), ('BUG', 'GHOST', 0.5), ('BUG', 'DARK', 2.0), ('BUG', 'STEEL', 0.5),
    ('ROCK', 'FIRE', 2.0), ('ROCK', 'ICE', 2.0), ('ROCK', 'FIGHTING', 0.5), ('ROCK', 'GROUND', 0.5), ('ROCK', 'FLYING', 2.0), ('ROCK', 'BUG', 2.0), ('ROCK', 'STEEL', 0.5),
    ('GHOST', 'NORMAL', 0.0), ('GHOST', 'PSYCHIC', 2.0), ('GHOST', 'DARK', 0.5), ('GHOST', 'STEEL', 0.5), ('GHOST', 'GHOST', 2.0),
    ('DRAGON', 'DRAGON', 2.0), ('DRAGON', 'STEEL', 0.5),
    ('DARK', 'FIGHTING', 0.5), ('DARK', 'PSYCHIC', 2.0), ('DARK', 'GHOST', 2.0), ('DARK', 'DARK', 0.5), ('DARK', 'STEEL', 0.5),
    ('STEEL', 'FIRE', 0.5), ('STEEL', 'WATER', 0.5), ('STEEL', 'ELECTRIC', 0.5), ('STEEL', 'ICE', 2.0), ('STEEL', 'ROCK', 2.0), ('STEEL', 'STEEL', 0.5),
    ('NORMAL', 'GHOST', 0.0), ('FIGHTING', 'GHOST', 0.0)
]

class AI_Logic:
    def __init__(self):
        # Load Moves to get Types and Category
        self.moves_df = pd.read_csv('all_attacks.csv')
        self.move_data = {}
        for _, row in self.moves_df.iterrows():
            m_name = str(row['Move']).strip()
            # Check if move is damaging (Power not 0 or '---')
            power_val = str(row['Power']).strip()
            is_damaging = power_val not in ['0', '---', 'nan']
            self.move_data[m_name] = {
                'type': str(row['Type']).strip().upper(),
                'is_damaging': is_damaging
            }

    def get_effectiveness(self, atk_type, def_type):
        for a, d, m in TYPE_INTERACTIONS:
            if a == atk_type.upper() and d == def_type.upper():
                return m
        return 1.0

    def calculate_priority(self, player_types, ai_pokemon, player_levitate):
        # 1. Defensive Score (Section 1)
        score = 10
        ai_types = []

        # Read Type1, Type2 from BFPokemon
        ai_types = [ai_pokemon.Type1.upper()]
        if isinstance(ai_pokemon.Type2, str) and ai_pokemon.Type2.lower() != 'nan':
             ai_types.append(ai_pokemon.Type2.upper())

        def apply_mult(s, m):
            if m == 0: return 0
            elif m < 1: return s // 2 # Floor
            elif m > 1: return s * 2
            return s

        # Player Primary vs AI
        if player_types:
            for t in ai_types:
                score = apply_mult(score, self.get_effectiveness(player_types[0], t))

        # Player Secondary vs AI
        if len(player_types) > 1:
            for t in ai_types:
                score = apply_mult(score, self.get_effectiveness(player_types[1], t))

        # Double Dip for Single-Typed Player
        if len(player_types) == 1:
            for t in ai_types:
                score = apply_mult(score, self.get_effectiveness(player_types[0], t))

        # 2. Check for SE Moves
        has_se = False
        for move_name in ai_pokemon.MoveList:
            if not isinstance(move_name, str): continue
            info = self.move_data.get(move_name)
            if not info or not info['is_damaging']: continue

            m_type = info['type']
            if m_type == 'GROUND' and player_levitate: continue

            e1 = self.get_effectiveness(m_type, player_types[0])
            e2 = self.get_effectiveness(m_type, player_types[1]) if len(player_types) > 1 else 1.0

            if (e1 * e2) >= 2.0:
                has_se = True
                break

        return (has_se, score)

    def filter_impossible_teams(self, current_teams, switch_in_mon, player_types, player_levitate):
        """
        Returns a filtered list of teams.
        """
        valid_teams = []

        # 1. Calculate Switch-In Priority
        switch_se, switch_score = self.calculate_priority(player_types, switch_in_mon, player_levitate)

        # Debug print to verify what the AI sees for the Switch-In
        print(f"Debug: Switch-in {switch_in_mon.Name} -> SE: {switch_se}, Score: {switch_score}")

        for team in current_teams:
            # Assume team is a tuple of PokemonSet objects
            is_possible_team = True

            for mon in team:
                # Skip the switch-in itself
                if mon.Name == switch_in_mon.Name: continue

                # Check priority of the hidden candidate
                cand_se, cand_score = self.calculate_priority(player_types, mon, player_levitate)

                # === LOGIC ===

                # Scenario A: The Switch-In was a "Strong" pick (SE Move Found)
                if switch_se:
                    # The Hidden Mon is IMPOSSIBLE if it is "Stronger"
                    # i.e., It also has an SE move AND a higher Defensive Score
                    if cand_se and (cand_score > switch_score):
                        is_possible_team = False

                # Scenario B: The Switch-In was a "Weak" pick (No SE Move)
                # This implies Section 1 failed for the Switch-In.
                # Therefore, NO available Pokemon could have had an SE move (with Score > 0).
                else:
                    # The Hidden Mon is IMPOSSIBLE if it would have triggered Section 1
                    # i.e., It HAS an SE move (and Score > 0)
                    if cand_se and (cand_score > 0):
                        is_possible_team = False


            if is_possible_team:
                valid_teams.append(team)

        return valid_teams
