"""Output presenter for CLI formatting using Rich."""

from __future__ import annotations

import json
from contextlib import contextmanager
from pathlib import Path
from typing import TYPE_CHECKING, Any

from rich import box
from rich.console import Console
from rich.panel import Panel
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.syntax import Syntax
from rich.table import Table

from portal.interfaces.cli.utils.worktree_helpers import (
    extract_worktree_display_info,
    format_branch_display,
)

if TYPE_CHECKING:
    from collections.abc import Iterator

    from portal.core.domain.models.color import WorktreeColor


class OutputPresenter:
    """Presenter for CLI output formatting using Rich."""

    def __init__(self) -> None:
        """Initialize the output presenter."""
        self.console = Console()

    def show_success(self, message: str, details: dict[str, Any] | None = None) -> None:
        """Show success message with optional details.

        Args:
            message: Success message to display
            details: Optional dictionary of key-value details to show
        """
        self.console.print(f"[green]✅ {message}[/green]")

        if details:
            for key, value in details.items():
                self.console.print(f"   [dim]{key}:[/dim] {value}")

    def show_error(self, message: str) -> None:
        """Show single error message.

        Args:
            message: Error message to display
        """
        self.console.print(f"[red]❌ {message}[/red]")

    def show_errors(self, errors: list[str]) -> None:
        """Show multiple error messages.

        Args:
            errors: List of error messages to display
        """
        for error in errors:
            self.show_error(error)

    def show_warning(self, message: str) -> None:
        """Show single warning message.

        Args:
            message: Warning message to display
        """
        self.console.print(f"[yellow]⚠️  {message}[/yellow]")

    def show_warnings(self, warnings: list[str]) -> None:
        """Show multiple warning messages.

        Args:
            warnings: List of warning messages to display
        """
        for warning in warnings:
            self.show_warning(warning)

    def show_info(self, message: str) -> None:
        """Show info message.

        Args:
            message: Info message to display
        """
        self.console.print(f"[cyan]ℹ️  {message}[/cyan]")

    def show_worktree_table(self, worktree_data: list[dict[str, Any]]) -> None:
        """Show worktrees in a table format.

        Args:
            worktree_data: List of dictionaries containing worktree and color info
        """
        table = Table(
            title="Git Worktrees",
            box=box.ROUNDED,
            show_header=True,
            header_style="bold cyan",
        )

        table.add_column("", width=2)  # Status indicator
        table.add_column("Color", width=8)
        table.add_column("Name", style="bold")
        table.add_column("Branch")
        table.add_column("Base", style="dim")
        table.add_column("Path")
        table.add_column("Status")

        for data in worktree_data:
            worktree = data["worktree"]
            color = data["color"]

            # Handle both dict and object types for worktree
            if isinstance(worktree, dict):
                is_current = worktree.get("is_current", False)
                name = worktree["name"]
                branch = worktree["branch"]
                base_branch = worktree.get("base_branch", "")
                path = worktree["path"]
                status = worktree["status"]
            else:
                is_current = getattr(worktree, "is_current", False)
                name = worktree.name
                branch = worktree.branch
                base_branch = getattr(worktree, "base_branch", "")
                path = str(worktree.path)
                status = worktree.status.value

            status_indicator = "●" if is_current else "○"
            color_indicator = f"[{color.hex}]⬤[/{color.hex}]"

            table.add_row(
                status_indicator,
                color_indicator + f" {color.name}",
                name,
                branch,
                base_branch if base_branch else "-",
                path,
                status,
            )

        self.console.print(table)

    def show_worktree_list(self, worktree_data: list[dict[str, Any]]) -> None:
        """Show worktrees in simple list format.

        Args:
            worktree_data: List of dictionaries containing worktree and color info
        """
        for data in worktree_data:
            worktree = data["worktree"]
            color = data["color"]

            # Handle both dict and object types for worktree
            if isinstance(worktree, dict):
                is_current = worktree.get("is_current", False)
                name = worktree["name"]
                path = worktree["path"]
            else:
                is_current = getattr(worktree, "is_current", False)
                name = worktree.name
                path = str(worktree.path)

            status = "●" if is_current else "○"
            color_text = f"[{color.hex}]{color.name}[/{color.hex}]"

            self.console.print(f"{status} {color_text} {name} → {path}")

    def show_worktree_simple(self, worktree_data: list[dict[str, Any]]) -> None:
        """Show worktrees in simple colored format - one line per worktree with current indicator and colored branch name.

        Args:
            worktree_data: List of dictionaries containing worktree and color info
        """
        for data in worktree_data:
            worktree = data["worktree"]
            color = data["color"]

            info = extract_worktree_display_info(worktree)
            indicator = "●" if info["is_current"] else "○"

            branch_display = format_branch_display(
                info["branch"],
                info["base_branch"],
                info["is_base"],
                colored=True,
                color_hex=color.hex,
            )

            self.console.print(f"{indicator} {branch_display}")

    def show_json(self, data: Any) -> None:
        """Show data as formatted JSON.

        Args:
            data: Data to serialize and display as JSON
        """
        json_data = self._to_json_serializable(data)
        json_str = json.dumps(json_data, indent=2)

        syntax = Syntax(json_str, "json", theme="monokai", line_numbers=False)
        self.console.print(syntax)

    def show_color_indicator(self, color: WorktreeColor) -> None:
        """Show color indicator with various formats.

        Args:
            color: WorktreeColor to display
        """
        panel_content = f"""[{color.hex}]███████████████[/{color.hex}] {color.name}

Hex: {color.hex}
RGB: {color.rgb}
Terminal: {color.ansi_code}"""

        panel = Panel(
            panel_content, title="Assigned Color", border_style=color.hex, box=box.ROUNDED
        )

        self.console.print(panel)

    def show_shell_command(self, command: str, description: str | None = None) -> None:
        """Show a shell command to execute.

        Args:
            command: Shell command to display
            description: Optional description of what the command does
        """
        if description:
            self.console.print(f"[dim]{description}[/dim]")

        self.console.print(f"[bold cyan]$ {command}[/bold cyan]")

    @contextmanager
    def progress(self, description: str) -> Iterator[Progress]:
        """Show progress spinner.

        Args:
            description: Description of the operation in progress

        Yields:
            Progress instance for custom operations
        """
        with Progress(
            SpinnerColumn(),
            TextColumn("[progress.description]{task.description}"),
            console=self.console,
            transient=True,
        ) as progress:
            progress.add_task(description)
            yield progress

    def _to_json_serializable(self, obj: Any) -> Any:
        """Convert object to JSON-serializable format.

        Args:
            obj: Object to convert

        Returns:
            JSON-serializable representation of the object
        """
        if hasattr(obj, "model_dump"):
            return obj.model_dump(mode="json")
        elif hasattr(obj, "__dict__"):
            return {
                k: self._to_json_serializable(v)
                for k, v in obj.__dict__.items()
                if not k.startswith("_")
            }
        elif isinstance(obj, list):
            return [self._to_json_serializable(item) for item in obj]
        elif isinstance(obj, dict):
            return {k: self._to_json_serializable(v) for k, v in obj.items()}
        elif isinstance(obj, Path):
            return str(obj)
        else:
            return obj
