"""
Sidebar - Metrics and status display panel

Provides sidebar component with:
- 42-character fixed width panel
- Real-time metrics (tokens, cost, files)
- Agent status
- MCP server list
- Session info
- Collapsible sections

Examples:
    # Create sidebar
    sidebar = Sidebar()
    sidebar.set_agent("build")
    sidebar.set_model("gpt-4o")
    sidebar.update_tokens(1000, 500)

    # Render
    lines = sidebar.render()
    for line in lines:
        print(line)
"""

from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import Optional


class SidebarSection(Enum):
    """Sidebar section"""
    AGENT = "agent"
    MODEL = "model"
    TOKENS = "tokens"
    COST = "cost"
    FILES = "files"
    MCP = "mcp"
    SESSION = "session"


@dataclass
class FileMetric:
    """File change metric"""
    path: str
    lines_added: int = 0
    lines_removed: int = 0
    modified_at: Optional[datetime] = None


@dataclass
class MCPServerMetric:
    """MCP server metric"""
    name: str
    status: str  # "connected", "disconnected", "error"
    tools_count: int = 0


class Sidebar:
    """
    Sidebar panel for metrics and status

    Fixed 42-character width panel matching OpenCode.
    Shows agent status, tokens, cost, files, MCP servers, and session info.
    """

    WIDTH = 42  # Fixed width to match OpenCode

    def __init__(self):
        """Initialize sidebar"""
        self.agent: str = "build"
        self.model: str = "gpt-4o"
        self.tokens_used: int = 0
        self.tokens_limit: int = 128000
        self.cost: float = 0.0
        self.files_modified: list[FileMetric] = []
        self.mcp_servers: list[MCPServerMetric] = []
        self.session_name: str = "default"
        self.session_messages: int = 0
        self.visible_sections: set[SidebarSection] = {
            SidebarSection.AGENT,
            SidebarSection.MODEL,
            SidebarSection.TOKENS,
            SidebarSection.COST,
        }

    def set_agent(self, agent: str):
        """Set current agent"""
        self.agent = agent

    def set_model(self, model: str, context_limit: int = 128000):
        """Set current model"""
        self.model = model
        self.tokens_limit = context_limit

    def update_tokens(self, prompt_tokens: int, completion_tokens: int):
        """Update token count"""
        self.tokens_used = prompt_tokens + completion_tokens

    def update_cost(self, cost: float):
        """Update total cost"""
        self.cost = cost

    def add_file_change(self, path: str, lines_added: int = 0, lines_removed: int = 0):
        """Record file change"""
        # Check if file already exists
        for file_metric in self.files_modified:
            if file_metric.path == path:
                file_metric.lines_added += lines_added
                file_metric.lines_removed += lines_removed
                file_metric.modified_at = datetime.now()
                return

        # Add new file
        self.files_modified.append(FileMetric(
            path=path,
            lines_added=lines_added,
            lines_removed=lines_removed,
            modified_at=datetime.now(),
        ))

    def add_mcp_server(self, name: str, status: str, tools_count: int = 0):
        """Add MCP server"""
        self.mcp_servers.append(MCPServerMetric(
            name=name,
            status=status,
            tools_count=tools_count,
        ))

    def set_session(self, name: str, messages: int = 0):
        """Set session info"""
        self.session_name = name
        self.session_messages = messages

    def show_section(self, section: SidebarSection):
        """Show a sidebar section"""
        self.visible_sections.add(section)

    def hide_section(self, section: SidebarSection):
        """Hide a sidebar section"""
        self.visible_sections.discard(section)

    def toggle_section(self, section: SidebarSection):
        """Toggle section visibility"""
        if section in self.visible_sections:
            self.visible_sections.discard(section)
        else:
            self.visible_sections.add(section)

    def _format_line(self, text: str, width: Optional[int] = None) -> str:
        """Format line to fixed width"""
        width = width or self.WIDTH
        if len(text) > width:
            return text[:width - 1] + "…"
        return text.ljust(width)

    def _render_section_header(self, title: str) -> str:
        """Render section header"""
        return self._format_line(f"╭─ {title} " + "─" * (self.WIDTH - len(title) - 4))

    def _render_section_footer(self) -> str:
        """Render section footer"""
        return self._format_line("╰" + "─" * (self.WIDTH - 1))

    def _render_agent_section(self) -> list[str]:
        """Render agent section"""
        if SidebarSection.AGENT not in self.visible_sections:
            return []

        icon = {"build": "🛠️", "plan": "📋", "oracle": "🔮"}.get(self.agent, "🤖")
        lines = [
            self._render_section_header("Agent"),
            self._format_line(f"│ {icon} {self.agent.title()}"),
            self._render_section_footer(),
        ]
        return lines

    def _render_model_section(self) -> list[str]:
        """Render model section"""
        if SidebarSection.MODEL not in self.visible_sections:
            return []

        lines = [
            self._render_section_header("Model"),
            self._format_line(f"│ {self.model}"),
            self._render_section_footer(),
        ]
        return lines

    def _render_tokens_section(self) -> list[str]:
        """Render tokens section"""
        if SidebarSection.TOKENS not in self.visible_sections:
            return []

        percentage = (self.tokens_used / self.tokens_limit * 100) if self.tokens_limit > 0 else 0
        indicator = "🔴" if percentage > 95 else "🟡" if percentage > 80 else "🟢"

        lines = [
            self._render_section_header("Tokens"),
            self._format_line(f"│ {indicator} {self.tokens_used:,} / {self.tokens_limit:,}"),
            self._format_line(f"│ {percentage:.1f}% used"),
            self._render_section_footer(),
        ]
        return lines

    def _render_cost_section(self) -> list[str]:
        """Render cost section"""
        if SidebarSection.COST not in self.visible_sections:
            return []

        lines = [
            self._render_section_header("Cost"),
            self._format_line(f"│ 💰 ${self.cost:.4f}"),
            self._render_section_footer(),
        ]
        return lines

    def _render_files_section(self) -> list[str]:
        """Render files section"""
        if SidebarSection.FILES not in self.visible_sections:
            return []

        if not self.files_modified:
            return []

        lines = [self._render_section_header("Files")]

        # Show recent files (up to 5)
        for file in self.files_modified[:5]:
            # Extract filename
            filename = file.path.split("/")[-1]
            if len(filename) > 25:
                filename = filename[:22] + "..."

            # Format changes
            changes = f"+{file.lines_added} -{file.lines_removed}"
            lines.append(self._format_line(f"│ {filename} {changes}"))

        if len(self.files_modified) > 5:
            lines.append(self._format_line(f"│ ... and {len(self.files_modified) - 5} more"))

        lines.append(self._render_section_footer())
        return lines

    def _render_mcp_section(self) -> list[str]:
        """Render MCP servers section"""
        if SidebarSection.MCP not in self.visible_sections:
            return []

        if not self.mcp_servers:
            return []

        lines = [self._render_section_header("MCP Servers")]

        for server in self.mcp_servers:
            status_icon = {"connected": "✓", "disconnected": "✗", "error": "⚠"}.get(server.status, "◌")
            lines.append(self._format_line(f"│ {status_icon} {server.name} ({server.tools_count} tools)"))

        lines.append(self._render_section_footer())
        return lines

    def _render_session_section(self) -> list[str]:
        """Render session section"""
        if SidebarSection.SESSION not in self.visible_sections:
            return []

        lines = [
            self._render_section_header("Session"),
            self._format_line(f"│ {self.session_name}"),
            self._format_line(f"│ {self.session_messages} messages"),
            self._render_section_footer(),
        ]
        return lines

    def render(self) -> list[str]:
        """
        Render full sidebar

        Returns:
            List of rendered lines
        """
        lines = [
            "╭" + "─" * (self.WIDTH - 2) + "╮",
            self._format_line("│ GROKNROLL"),
        ]

        # Add all visible sections
        sections = [
            self._render_agent_section(),
            self._render_model_section(),
            self._render_tokens_section(),
            self._render_cost_section(),
            self._render_files_section(),
            self._render_mcp_section(),
            self._render_session_section(),
        ]

        for section_lines in sections:
            if section_lines:
                lines.extend(section_lines)

        lines.append("╰" + "─" * (self.WIDTH - 2) + "╯")
        return lines

    def render_compact(self) -> str:
        """
        Render compact one-line summary

        Returns:
            Single line summary
        """
        percentage = (self.tokens_used / self.tokens_limit * 100) if self.tokens_limit > 0 else 0
        indicator = "🔴" if percentage > 95 else "🟡" if percentage > 80 else "🟢"

        parts = [
            f"{self.agent}",
            f"{self.model}",
            f"{indicator} {percentage:.0f}%",
            f"${self.cost:.2f}",
        ]

        if self.files_modified:
            parts.append(f"{len(self.files_modified)} files")

        return " │ ".join(parts)


# Convenience functions

def create_sidebar() -> Sidebar:
    """
    Create a sidebar with default settings

    Returns:
        Sidebar instance
    """
    return Sidebar()
