"""
Main entry point for CNY26 Chinese New Year celebration.
"""

import random
import sys
import time
import threading
from typing import List, Optional

from rich.console import Console, Group
from rich.live import Live
from rich.panel import Panel
from rich.text import Text
from rich.align import Align

from .canvas import BrailleCanvas
from .firework import Firework
from .horse import get_centered_horse
from .sound import SoundManager
from .utils import (
    get_countdown_to_cny_2026,
    render_text_on_canvas,
)

# Terminal input handling
if sys.platform == "win32":
    import msvcrt

    def get_key() -> Optional[str]:
        """Get a key press (non-blocking) on Windows."""
        if msvcrt.kbhit():
            key = msvcrt.getch()
            if key == b" ":
                return "space"
            elif key == b"\x1b":
                return "escape"
            elif key == b"\x03":  # Ctrl+C
                return "ctrl_c"
        return None

else:
    import select
    import termios
    import tty

    def get_key() -> Optional[str]:
        """Get a key press (non-blocking) on Unix."""
        if not sys.stdin.isatty():
            return None
        try:
            if select.select([sys.stdin], [], [], 0)[0]:
                key = sys.stdin.read(1)
                if key == " ":
                    return "space"
                elif key == "\x1b":
                    return "escape"
                elif key == "\x03":  # Ctrl+C
                    return "ctrl_c"
        except (OSError, IOError):
            pass
        return None


class CNY26App:
    """Main application for Chinese New Year 2026 celebration."""

    def __init__(self):
        self.console = Console()
        self.running = False
        self.sound_manager: Optional[SoundManager] = None

        # Target 60 FPS
        self.target_fps = 60
        self.frame_time = 1.0 / self.target_fps

        # Firework auto-spawn settings
        self.auto_firework_interval = 0.5  # seconds (more frequent)
        self.time_since_last_firework = 0.0

        # Canvas dimensions (will be set based on terminal size)
        self.canvas_width = 0
        self.canvas_height = 0

        # Game objects
        self.fireworks: List[Firework] = []
        self.canvas: Optional[BrailleCanvas] = None

        # Camera position for 3D effects
        self.camera_z = 0.0

    def initialize(self):
        """Initialize the application."""
        # Get terminal size
        term_width = self.console.width
        term_height = self.console.height

        # Calculate canvas size (leave room for borders, padding, and horse)
        # Each braille character is 2x4 pixels
        # Reserve bottom portion for horse ASCII art (about 8 lines)
        self.canvas_width = (term_width - 4) * 2
        self.canvas_height = (term_height - 12) * 4

        # Initialize canvas
        self.canvas = BrailleCanvas(self.canvas_width, self.canvas_height)

        # Initialize sound manager
        self.sound_manager = SoundManager()

        # Spawn initial fireworks
        for _ in range(6):
            self._spawn_firework()

    def _spawn_firework(self):
        """Spawn a new firework."""
        if self.canvas:
            firework = Firework(
                self.canvas_width,
                self.canvas_height,
                self.camera_z,
                self.sound_manager,
            )
            self.fireworks.append(firework)

    def update(self, dt: float):
        """Update all game objects."""
        # Auto-spawn fireworks
        self.time_since_last_firework += dt
        if self.time_since_last_firework >= self.auto_firework_interval:
            self.time_since_last_firework = 0.0
            self.auto_firework_interval = random.uniform(0.3, 0.8)
            self._spawn_firework()

        # Update fireworks
        for firework in self.fireworks:
            firework.update(dt)

        # Remove finished fireworks
        self.fireworks = [f for f in self.fireworks if not f.is_finished()]

    def render(self) -> str:
        """Render the scene and return as string."""
        if not self.canvas:
            return ""

        # Clear canvas
        self.canvas.clear()

        # Render fireworks
        for firework in self.fireworks:
            firework.render(self.canvas, self.camera_z)

        # Render "Year of Horse" text in the center of screen
        text_color = BrailleCanvas.rgb_color(255, 215, 0)  # Gold
        text = "YEAR OF HORSE"
        # Calculate centered position (both horizontal and vertical)
        char_width = 6 * 2  # Approximate character width with scale 2
        text_height = 5 * 2  # Approximate text height with scale 2
        text_x = (self.canvas_width - len(text) * char_width) // 2 + 10
        text_y = (self.canvas_height - text_height) // 2 + 5
        render_text_on_canvas(self.canvas, text, text_x, text_y, text_color, scale=2)

        return self.canvas.render()

    def handle_input(self, key: Optional[str]) -> bool:
        """
        Handle keyboard input.

        Returns:
            False if should exit, True otherwise
        """
        if key == "escape" or key == "ctrl_c":
            return False
        elif key == "space":
            self._spawn_firework()
        return True

    def run(self):
        """Main application loop."""
        self.running = True
        self.initialize()

        # Set terminal to raw mode for input handling (Unix only)
        old_settings = None
        is_tty = sys.stdin.isatty()
        if sys.platform != "win32" and is_tty:
            try:
                old_settings = termios.tcgetattr(sys.stdin)
                tty.setcbreak(sys.stdin.fileno())
            except (termios.error, OSError):
                # stdin is not a terminal, continue without raw mode
                old_settings = None

        try:
            last_time = time.perf_counter()

            with Live(
                Panel("", title="Chinese New Year 2026", border_style="red"),
                console=self.console,
                refresh_per_second=self.target_fps,
                screen=True,
            ) as live:
                while self.running:
                    # Calculate delta time
                    current_time = time.perf_counter()
                    dt = current_time - last_time
                    last_time = current_time

                    # Handle input
                    key = get_key()
                    if not self.handle_input(key):
                        break

                    # Update game state
                    self.update(dt)

                    # Render fireworks
                    frame = self.render()

                    # Get horse ASCII art
                    horse_art = get_centered_horse(self.console.width - 4)

                    # Get countdown for subtitle
                    countdown_str, cny_reached, _ = get_countdown_to_cny_2026()
                    if cny_reached:
                        subtitle = "Happy Chinese New Year 2026!"
                    else:
                        subtitle = f"Countdown: {countdown_str}"

                    # Combine fireworks canvas and horse
                    combined = Text.from_ansi(frame)
                    combined.append("\n")
                    combined.append(horse_art, style="bold yellow")

                    # Update display
                    panel = Panel(
                        combined,
                        title="Chinese New Year 2026 - Year of the Horse",
                        subtitle=subtitle,
                        border_style="bright_red",
                    )
                    live.update(panel)

                    # Frame rate limiting
                    elapsed = time.perf_counter() - current_time
                    if elapsed < self.frame_time:
                        time.sleep(self.frame_time - elapsed)

        except KeyboardInterrupt:
            pass
        finally:
            # Restore terminal settings (Unix only)
            if sys.platform != "win32" and old_settings:
                termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_settings)

            # Cleanup sound
            if self.sound_manager:
                self.sound_manager.stop()

            self.running = False


def main():
    """Entry point for the application."""
    app = CNY26App()
    app.run()


if __name__ == "__main__":
    main()
