"""
UI effects and animations for console interface.
Handles loading animations, live displays, and other visual effects.
"""

from __future__ import annotations

import time
import threading
import itertools
import random
from rich.live import Live
from rich.markdown import Markdown
from rich.panel import Panel

from .constants import CODE_THEME, RICH_STYLE_GRAY, RICH_STYLE_GREEN

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from .console_ui import ConsoleUI


class UIEffects:
    """Handles UI effects like loading animations and live displays."""

    def __init__(self, console_ui: ConsoleUI):
        """Initialize UI effects with a console instance."""
        self.console = console_ui.console
        self.live = None
        self._loading_stop_event = None
        self._loading_thread = None
        self._visible_buffer = 0
        self.message_handler = console_ui.message_handler

    def _loading_animation(self, stop_event):
        """Display a loading animation in the terminal."""
        spinner = itertools.cycle(["⣾", "⣽", "⣻", "⢿", "⡿", "⣟", "⣯", "⣷"])
        fun_words = [
            "Pondering",
            "Cogitating",
            "Ruminating",
            "Contemplating",
            "Brainstorming",
            "Calculating",
            "Processing",
            "Analyzing",
            "Deciphering",
            "Meditating",
            "Daydreaming",
            "Scheming",
            "Brewing",
            "Conjuring",
            "Inventing",
            "Imagining",
        ]
        fun_word = random.choice(fun_words)

        with Live(
            "", console=self.console, auto_refresh=True, refresh_per_second=10
        ) as live:
            while not stop_event.is_set():
                live.update(f"{fun_word} {next(spinner)}")
                time.sleep(0.1)  # Control animation speed
            live.update("")  # Clear the live display when done
            live.stop()  # Stop the live display

    def start_loading_animation(self):
        """Start the loading animation."""
        if self._loading_thread and self._loading_thread.is_alive():
            return  # Already running

        self._loading_stop_event = threading.Event()
        self._loading_thread = threading.Thread(
            target=self._loading_animation, args=(self._loading_stop_event,)
        )
        self._loading_thread.daemon = True
        self._loading_thread.start()

    def stop_loading_animation(self):
        """Stop the loading animation."""
        if self._loading_stop_event:
            self._loading_stop_event.set()
            self._loading_stop_event = None
        if self._loading_thread and self._loading_thread.is_alive():
            self._loading_thread.join(timeout=0.5)
            self._loading_thread = None

    def start_streaming_response(self, agent_name: str):
        """Start streaming the assistant's response."""
        from .constants import RICH_STYLE_GREEN_BOLD
        from rich.text import Text

        header = Text(f"🤖 {agent_name.upper()}:", style=RICH_STYLE_GREEN_BOLD)

        live_panel = Panel("", title=header, border_style=RICH_STYLE_GREEN)

        self.live = Live(
            live_panel,
            refresh_per_second=60,
            console=self.console,
            vertical_overflow="crop",
        )
        self.live.start()

    def scroll_live_display(self, direction: str):
        speed = 10
        if direction == "up":
            self._visible_buffer = max(0, self._visible_buffer - speed)
        elif direction == "down":
            self._visible_buffer += speed

    def update_live_display(self, chunk: str):
        """Update the live display with a new chunk of the response."""
        if not self.live:
            self.start_streaming_response(self.message_handler.agent.name)

        updated_text = chunk

        # Only show the last part that fits in the console
        lines = updated_text.split("\n")
        height_limit = (
            self.console.size.height - 5
        )  # leave some space for other elements
        if len(lines) > height_limit:
            lines = lines[self._visible_buffer : self._visible_buffer + height_limit]

        if self.live:
            from .constants import RICH_STYLE_GREEN_BOLD
            from rich.text import Text

            header = Text(
                f"🤖 {self.message_handler.agent.name.upper()}:",
                style=RICH_STYLE_GREEN_BOLD,
            )
            subtitle = Text("(Use Ctrl+U/Ctrl+D to scroll)", style=RICH_STYLE_GRAY)
            live_panel = Panel(
                Markdown("\n".join(lines), code_theme=CODE_THEME),
                title=header,
                subtitle=subtitle,
                title_align="left",
                border_style=RICH_STYLE_GREEN,
            )
            self.live.update(live_panel)

    def finish_live_update(self):
        """Stop the live update display."""
        self._visible_buffer = 0
        if self.live:
            self.console.print(self.live.get_renderable())
            self.live.update("")
            self.live.stop()
            self.live = None

    def finish_response(self, response: str):
        """Finalize and display the complete response."""
        from .constants import RICH_STYLE_GREEN_BOLD
        from rich.text import Text

        self._visible_buffer = 0

        if self.live:
            self.live.update(Text("", end=""))
            self.live.stop()
            self.live = None

        # Replace \n with two spaces followed by \n for proper Markdown line breaks
        markdown_formatted_response = response.replace("\n", "  \n")

        if not markdown_formatted_response.strip():
            return

        header = Text(
            f"🤖 {self.message_handler.agent.name.upper()}:",
            style=RICH_STYLE_GREEN_BOLD,
        )
        assistant_panel = Panel(
            Markdown(markdown_formatted_response, code_theme=CODE_THEME),
            title=header,
            title_align="left",
            border_style=RICH_STYLE_GREEN,
        )
        self.console.print(assistant_panel)

    def cleanup(self):
        """Clean up all running effects."""
        self.stop_loading_animation()
        self.finish_live_update()
