import logging
import time
from datetime import datetime, timezone
from typing import Any, Dict, Optional

from PIL import Image, ImageDraw, ImageFont

from src.base_classes.data_sources import ESPNDataSource
from src.base_classes.sports import SportsCore, SportsLive
from src.cache_manager import CacheManager
from src.display_manager import DisplayManager


class Hockey(SportsCore):
    """Base class for hockey sports with common functionality."""

    def __init__(
        self,
        config: Dict[str, Any],
        display_manager: DisplayManager,
        cache_manager: CacheManager,
        logger: logging.Logger,
        sport_key: str,
    ):
        super().__init__(config, display_manager, cache_manager, logger, sport_key)
        self.data_source = ESPNDataSource(logger)
        self.sport = "hockey"
        self.show_shots_on_goal = self.mode_config.get("show_shots_on_goal", False)

    def _extract_game_details(self, game_event: Dict) -> Optional[Dict]:
        """Extract relevant game details from ESPN NCAA FB API response."""
        # --- THIS METHOD MAY NEED ADJUSTMENTS FOR NCAA FB API DIFFERENCES ---
        try:
            details, home_team, away_team, status, situation = (
                self._extract_game_details_common(game_event)
            )
        except Exception as e:
            self.logger.error(f"Error in _extract_game_details_common: {e}", exc_info=True)
            return None
            
        if details is None or home_team is None or away_team is None or status is None:
            self.logger.warning(f"Missing required data in game event {game_event.get('id')}")
            return None
        try:
            competition = game_event["competitions"][0]
            status = competition["status"]
            powerplay = False
            penalties = ""
            home_team_saves = next(
                (
                    int(c["displayValue"])
                    for c in home_team["statistics"]
                    if c.get("name") == "saves"
                ),
                0,
            )
            home_team_saves_per = next(
                (
                    float(c["displayValue"])
                    for c in home_team["statistics"]
                    if c.get("name") == "savePct"
                ),
                0.0,
            )
            away_team_saves = next(
                (
                    int(c["displayValue"])
                    for c in away_team["statistics"]
                    if c.get("name") == "saves"
                ),
                0,
            )
            away_team_saves_per = next(
                (
                    float(c["displayValue"])
                    for c in away_team["statistics"]
                    if c.get("name") == "savePct"
                ),
                0.0,
            )

            home_shots = 0
            away_shots = 0
            if home_team_saves_per > 0:
                away_shots = round(home_team_saves / home_team_saves_per)
            if away_team_saves_per > 0:
                home_shots = round(away_team_saves / away_team_saves_per)
            status_short = status["type"].get("shortDetail", "")

            if situation and status["type"]["state"] == "in":
                # Detect scoring events from status detail
                # status_detail = status["type"].get("detail", "")
                powerplay = situation.get("isPowerPlay", False)
                penalties = situation.get("penalties", "")

            # Format period/quarter
            period = status.get("period", 0)
            
            # Check for custom period text (used by EOJHL to preserve "1st", "2nd", "3rd" from API)
            period_text = status.get("customPeriodText", "")
            display_clock = status.get("displayClock", "0:00")
            
            self.logger.info(f"Status parsing - period: {period}, customPeriodText: '{period_text}', displayClock: '{display_clock}'")
            
            if not period_text:
                # Default period text formatting
                if status["type"]["state"] == "in":
                    if period == 0:
                        period_text = "Start"  # Before kickoff
                    elif period >= 1 and period <= 3:
                        period_text = f"P{period}"  # OT starts after Q4
                    elif period > 3:
                        period_text = f"OT{period - 3}"  # OT starts after Q4
                elif status["type"]["state"] == "post":
                    if period > 3:
                        period_text = "FINAL/OT"
                    elif period > 4:
                        period_text = "FINAL/SO"
                    else:
                        period_text = "FINAL"
                elif status["type"]["state"] == "pre":
                    period_text = details.get("game_time", "")  # Show time for upcoming

            details.update(
                {
                    "period": period,
                    "period_text": period_text,  # Formatted quarter/status
                    "clock": status.get("displayClock", "0:00"),
                    "power_play": powerplay,
                    "penalties": penalties,
                    "home_shots": home_shots,
                    "away_shots": away_shots,
                }
            )

            # Basic validation (can be expanded)
            if not details["home_abbr"] or not details["away_abbr"]:
                self.logger.warning(
                    f"Missing team abbreviation in event: {details['id']}"
                )
                return None

            self.logger.info(
                f"Parsed game: {details['away_abbr']}@{details['home_abbr']}, period_text='{period_text}', clock='{status.get('displayClock', '0:00')}', Live: {details['is_live']}"
            )

            return details
        except Exception as e:
            # Log the problematic event structure if possible
            self.logger.error(
                f"Error extracting game details: {e} from event: {game_event.get('id')}",
                exc_info=True,
            )
            return None


class HockeyLive(Hockey, SportsLive):
    def __init__(
        self,
        config: Dict[str, Any],
        display_manager: DisplayManager,
        cache_manager: CacheManager,
        logger: logging.Logger,
        sport_key: str,
    ):
        super().__init__(config, display_manager, cache_manager, logger, sport_key)

    def _test_mode_update(self):
        if self.current_game and self.current_game["is_live"]:
            # For testing, we'll just update the clock to show it's working
            minutes = int(self.current_game["clock"].split(":")[0])
            seconds = int(self.current_game["clock"].split(":")[1])
            seconds -= 1
            if seconds < 0:
                seconds = 59
                minutes -= 1
                if minutes < 0:
                    minutes = 19
                    if self.current_game["period"] < 3:
                        self.current_game["period"] += 1
                    else:
                        self.current_game["period"] = 1
            self.current_game["clock"] = f"{minutes:02d}:{seconds:02d}"
            # Always update display in test mode

    def _draw_scorebug_layout(self, game: Dict, force_clear: bool = False) -> None:
        """Draw the detailed scorebug layout for a live NCAA FB game."""  # Updated docstring
        try:
            main_img = Image.new(
                "RGBA", (self.display_width, self.display_height), (0, 0, 0, 255)
            )
            overlay = Image.new(
                "RGBA", (self.display_width, self.display_height), (0, 0, 0, 0)
            )
            draw_overlay = ImageDraw.Draw(
                overlay
            )  # Draw text elements on overlay first
            home_logo = self._load_and_resize_logo(
                game["home_id"],
                game["home_abbr"],
                game["home_logo_path"],
                game.get("home_logo_url"),
            )
            away_logo = self._load_and_resize_logo(
                game["away_id"],
                game["away_abbr"],
                game["away_logo_path"],
                game.get("away_logo_url"),
            )

            if not home_logo or not away_logo:
                self.logger.error(
                    f"Failed to load logos for live game: {game.get('id')}"
                )  # Changed log prefix
                # Draw placeholder text if logos fail
                draw_final = ImageDraw.Draw(main_img.convert("RGB"))
                self._draw_text_with_outline(
                    draw_final, "Logo Error", (5, 5), self.fonts["status"]
                )
                self.display_manager.image.paste(main_img.convert("RGB"), (0, 0))
                self.display_manager.update_display()
                return

            center_y = self.display_height // 2

            # Draw logos (shifted slightly more inward than NHL perhaps)
            home_x = (
                self.display_width - home_logo.width + 10
            )  # adjusted from 18 # Adjust position as needed
            home_y = center_y - (home_logo.height // 2)
            main_img.paste(home_logo, (home_x, home_y), home_logo)

            away_x = -10  # adjusted from 18 # Adjust position as needed
            away_y = center_y - (away_logo.height // 2)
            main_img.paste(away_logo, (away_x, away_y), away_logo)

            # --- Draw Text Elements on Overlay ---
            # Note: Rankings are now handled in the records/rankings section below

            # Period/Quarter and Clock (Top center)
            period_text_val = game.get('period_text', '')
            clock_val = game.get('clock', '')
            self.logger.info(f"Rendering clock - period_text: '{period_text_val}', clock: '{clock_val}'")
            
            period_clock_text = (
                f"{period_text_val} {clock_val}".strip()
            )
            if game.get("is_period_break"):
                period_clock_text = game.get("status_text", "Period Break")

            status_width = draw_overlay.textlength(
                period_clock_text, font=self.fonts["time"]
            )
            status_x = (self.display_width - status_width) // 2
            status_y = 1  # Position at top
            self._draw_text_with_outline(
                draw_overlay,
                period_clock_text,
                (status_x, status_y),
                self.fonts["time"],
            )

            # Scores (centered, slightly above bottom)
            home_score = str(game.get("home_score", "0"))
            away_score = str(game.get("away_score", "0"))
            score_text = f"{away_score}-{home_score}"
            score_width = draw_overlay.textlength(score_text, font=self.fonts["score"])
            score_x = (self.display_width - score_width) // 2
            score_y = (
                self.display_height // 2
            ) - 3  # centered #from 14 # Position score higher
            self._draw_text_with_outline(
                draw_overlay, score_text, (score_x, score_y), self.fonts["score"]
            )

            # Shots on Goal
            if self.show_shots_on_goal:
                shots_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
                home_shots = str(game.get("home_shots", "0"))
                away_shots = str(game.get("away_shots", "0"))
                shots_text = f"{away_shots}   SHOTS   {home_shots}"
                shots_bbox = draw_overlay.textbbox((0, 0), shots_text, font=shots_font)
                shots_height = shots_bbox[3] - shots_bbox[1]
                shots_y = self.display_height - shots_height - 1
                shots_width = draw_overlay.textlength(shots_text, font=shots_font)
                shots_x = (self.display_width - shots_width) // 2
                self._draw_text_with_outline(
                    draw_overlay, shots_text, (shots_x, shots_y), shots_font
                )

            # Draw odds if available
            if "odds" in game and game["odds"]:
                self._draw_dynamic_odds(
                    draw_overlay, game["odds"], self.display_width, self.display_height
                )

            # Draw records or rankings if enabled
            if self.show_records or self.show_ranking:
                try:
                    record_font = ImageFont.truetype("assets/fonts/4x6-font.ttf", 6)
                    self.logger.debug(f"Loaded 6px record font successfully")
                except IOError:
                    record_font = ImageFont.load_default()
                    self.logger.warning(
                        f"Failed to load 6px font, using default font (size: {record_font.size})"
                    )

                # Get team abbreviations
                away_abbr = game.get("away_abbr", "")
                home_abbr = game.get("home_abbr", "")

                record_bbox = draw_overlay.textbbox((0, 0), "0-0", font=record_font)
                record_height = record_bbox[3] - record_bbox[1]
                record_y = self.display_height - record_height - 1
                self.logger.debug(
                    f"Record positioning: height={record_height}, record_y={record_y}, display_height={self.display_height}"
                )

                # Display away team info
                if away_abbr:
                    if self.show_ranking and self.show_records:
                        # When both rankings and records are enabled, rankings replace records completely
                        away_rank = self._team_rankings_cache.get(away_abbr, 0)
                        if away_rank > 0:
                            away_text = f"#{away_rank}"
                        else:
                            # Show nothing for unranked teams when rankings are prioritized
                            away_text = ""
                    elif self.show_ranking:
                        # Show ranking only if available
                        away_rank = self._team_rankings_cache.get(away_abbr, 0)
                        if away_rank > 0:
                            away_text = f"#{away_rank}"
                        else:
                            away_text = ""
                    elif self.show_records:
                        # Show record only when rankings are disabled
                        away_text = game.get("away_record", "")
                    else:
                        away_text = ""

                    if away_text:
                        away_record_x = 3
                        self.logger.debug(
                            f"Drawing away ranking '{away_text}' at ({away_record_x}, {record_y}) with font size {record_font.size if hasattr(record_font, 'size') else 'unknown'}"
                        )
                        self._draw_text_with_outline(
                            draw_overlay,
                            away_text,
                            (away_record_x, record_y),
                            record_font,
                        )

                # Display home team info
                if home_abbr:
                    if self.show_ranking and self.show_records:
                        # When both rankings and records are enabled, rankings replace records completely
                        home_rank = self._team_rankings_cache.get(home_abbr, 0)
                        if home_rank > 0:
                            home_text = f"#{home_rank}"
                        else:
                            # Show nothing for unranked teams when rankings are prioritized
                            home_text = ""
                    elif self.show_ranking:
                        # Show ranking only if available
                        home_rank = self._team_rankings_cache.get(home_abbr, 0)
                        if home_rank > 0:
                            home_text = f"#{home_rank}"
                        else:
                            home_text = ""
                    elif self.show_records:
                        # Show record only when rankings are disabled
                        home_text = game.get("home_record", "")
                    else:
                        home_text = ""

                    if home_text:
                        home_record_bbox = draw_overlay.textbbox(
                            (0, 0), home_text, font=record_font
                        )
                        home_record_width = home_record_bbox[2] - home_record_bbox[0]
                        home_record_x = self.display_width - home_record_width - 3
                        self.logger.debug(
                            f"Drawing home ranking '{home_text}' at ({home_record_x}, {record_y}) with font size {record_font.size if hasattr(record_font, 'size') else 'unknown'}"
                        )
                        self._draw_text_with_outline(
                            draw_overlay,
                            home_text,
                            (home_record_x, record_y),
                            record_font,
                        )

            # Composite the text overlay onto the main image
            main_img = Image.alpha_composite(main_img, overlay)
            main_img = main_img.convert("RGB")  # Convert for display

            # Display the final image
            self.display_manager.image.paste(main_img, (0, 0))
            self.display_manager.update_display()  # Update display here for live

        except Exception as e:
            self.logger.error(
                f"Error displaying live Hockey game: {e}", exc_info=True
            )  # Changed log prefix