"""Unified UI components for Markitai CLI.

This module provides consistent visual components for CLI output,
including status messages, titles, and progress indicators.

Usage:
    from markitai.cli.ui import title, success, error, warning, info

    title("Processing Files")
    success("File converted successfully")
    error("Conversion failed", detail="Invalid format")
"""

from __future__ import annotations

from typing import TYPE_CHECKING

from rich.console import Console

from markitai.cli.console import get_console

if TYPE_CHECKING:
    from markitai.config import MarkitaiConfig

# Symbol constants for visual markers
MARK_SUCCESS = "\u2713"  # Checkmark
MARK_ERROR = "\u2717"  # Cross
MARK_WARNING = "!"  # Exclamation
MARK_INFO = "\u2022"  # Bullet
MARK_TITLE = "\u25c6"  # Diamond
MARK_LINE = "\u2502"  # Vertical line


def term_width(console: Console | None = None) -> int:
    """Return current terminal width."""
    c = console or get_console()
    return c.width


def truncate(text: str, max_len: int) -> str:
    """Truncate text to max_len, appending '...' if trimmed."""
    if max_len < 4:
        return text[:max_len]
    if len(text) <= max_len:
        return text
    return text[: max_len - 3] + "..."


def summarize_active_items(
    items: list[str],
    *,
    max_items: int = 3,
    max_len: int | None = None,
) -> str:
    """Summarize active concurrent items for compact progress displays.

    Args:
        items: Active item labels in display order.
        max_items: Maximum number of labels to show before collapsing the rest.
        max_len: Optional maximum display length.

    Returns:
        Compact summary string such as ``"a.txt, b.txt +2"``.
    """
    unique_items = [item.strip() for item in items if item and item.strip()]
    unique_items = list(dict.fromkeys(unique_items))
    if not unique_items:
        return ""

    shown = unique_items[:max_items]
    remaining = len(unique_items) - len(shown)
    summary = ", ".join(shown)
    if remaining > 0:
        summary = f"{summary} +{remaining}"
    if max_len is not None:
        summary = truncate(summary, max_len)
    return summary


def title(text: str, *, console: Console | None = None) -> None:
    """Display a title with diamond symbol.

    Args:
        text: The title text to display.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print(f"[cyan]{MARK_TITLE}[/] [bold]{text}[/]")
    c.print()


def success(text: str, *, console: Console | None = None) -> None:
    """Display a success message with checkmark.

    Args:
        text: The success message to display.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print(f"  [green]{MARK_SUCCESS}[/] {text}")


def error(
    text: str, *, detail: str | None = None, console: Console | None = None
) -> None:
    """Display an error message with cross symbol.

    Args:
        text: The error message to display.
        detail: Optional detail text shown on a separate line.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print(f"  [red]{MARK_ERROR}[/] {text}")
    if detail:
        c.print(f"    [dim]{MARK_LINE} {detail}[/]")


def warning(
    text: str, *, detail: str | None = None, console: Console | None = None
) -> None:
    """Display a warning message with exclamation symbol.

    Args:
        text: The warning message to display.
        detail: Optional detail text shown on a separate line.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print(f"  [yellow]{MARK_WARNING}[/] {text}")
    if detail:
        c.print(f"    [dim]{MARK_LINE} {detail}[/]")


def info(text: str, *, console: Console | None = None) -> None:
    """Display an info message with bullet symbol.

    Args:
        text: The info message to display.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print(f"  [dim]{MARK_INFO}[/] {text}")


def step(text: str, *, console: Console | None = None) -> None:
    """Display a step message with vertical line symbol.

    Args:
        text: The step message to display.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print(f"  [dim]{MARK_LINE}[/] {text}")


def section(text: str, *, console: Console | None = None) -> None:
    """Display a section header in bold.

    Args:
        text: The section header text to display.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print(f"[bold]{text}[/]")


def summary(text: str, *, console: Console | None = None) -> None:
    """Display a summary message with checkmark and leading blank line.

    Args:
        text: The summary message to display.
        console: Optional console for output (defaults to shared console).
    """
    c = console or get_console()
    c.print()
    c.print(f"[green]{MARK_SUCCESS}[/] {text}")


def build_feature_str(cfg: MarkitaiConfig) -> str:
    """Build a human-readable feature summary string from config.

    Separates LLM-dependent features from local processing features.
    LLM features: LLM, alt, desc.
    Local features: OCR (RapidOCR), screenshot (Playwright).

    Args:
        cfg: The full Markitai configuration.

    Returns:
        A Rich-formatted string like "LLM alt desc | OCR screenshot".
    """
    llm_features: list[str] = []
    local_features: list[str] = []

    if cfg.llm.enabled:
        llm_features.append("[green]LLM[/green]")
    if cfg.image.alt_enabled:
        llm_features.append("[green]alt[/green]")
    if cfg.image.desc_enabled:
        llm_features.append("[green]desc[/green]")

    if cfg.ocr.enabled:
        local_features.append("[green]OCR[/green]")
    if cfg.screenshot.enabled:
        local_features.append("[green]screenshot[/green]")

    parts = []
    if llm_features:
        parts.append(" ".join(llm_features))
    if local_features:
        parts.append(" ".join(local_features))

    return " | ".join(parts) if parts else "[dim]none[/dim]"
