from __future__ import annotations

import sys
from dataclasses import dataclass
from typing import Literal

from rich.console import Console
from rich.markdown import Markdown
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

Status = Literal["OK", "WARN", "FAIL"]

console = Console()
error_console = Console(stderr=True)


@dataclass(frozen=True, slots=True)
class CheckResult:
    status: Status
    label: str
    detail: str


def is_pretty() -> bool:
    return console.is_terminal


def print_response(text: str) -> None:
    if not is_pretty():
        print(text)
        return

    console.print(
        Panel(
            Markdown(text),
            title="Assistant",
            border_style="cyan",
            padding=(1, 2),
        )
    )


def print_cli_welcome(*, version: str, model: str) -> None:
    if not is_pretty():
        print(f"cli-demo {version} (model: {model})")
        print("Run 'cli-demo --help' to list commands.")
        return

    console.print(
        Panel(
            "[bold cyan]cli-demo[/]\n"
            "OpenAI-powered CLI playground\n\n"
            f"[cyan]Version[/]: {version}\n"
            f"[cyan]Model[/]: {model}\n\n"
            "[dim]Try:[/] cli-demo chat   [dim]or[/]   cli-demo --help",
            title="AI CLI",
            border_style="cyan",
            padding=(1, 2),
        )
    )


def print_error(message: str) -> None:
    if is_pretty():
        error_console.print(f"[bold red]Error:[/] {message}")
        return
    print(f"Error: {message}", file=sys.stderr)


def print_internal_error(message: str) -> None:
    if is_pretty():
        error_console.print(f"[bold red]Internal error:[/] {message}")
        return
    print(f"Internal error: {message}", file=sys.stderr)


def print_success(message: str) -> None:
    if is_pretty():
        console.print(f"[bold green]{message}[/]")
        return
    print(message)


def print_info(message: str) -> None:
    if is_pretty():
        console.print(f"[cyan]{message}[/]")
        return
    print(message)


def print_warning(message: str) -> None:
    if is_pretty():
        console.print(f"[yellow]{message}[/]")
        return
    print(message)


def print_doctor_results(results: list[CheckResult]) -> None:
    if not is_pretty():
        for result in results:
            print(f"[{result.status}] {result.label}: {result.detail}")
        return

    table = Table(title="CLI Doctor", show_header=True, header_style="bold cyan")
    table.add_column("Status", style="bold", no_wrap=True)
    table.add_column("Check", style="cyan", no_wrap=True)
    table.add_column("Detail")
    for result in results:
        table.add_row(_status_text(result.status), result.label, result.detail)
    console.print(table)

    failures = sum(1 for result in results if result.status == "FAIL")
    warnings = sum(1 for result in results if result.status == "WARN")
    if failures:
        summary = f"{failures} failure(s), {warnings} warning(s). Fix failures before using AI commands."
        style = "red"
    elif warnings:
        summary = f"Ready with {warnings} warning(s)."
        style = "yellow"
    else:
        summary = "Ready. All checks passed."
        style = "green"

    console.print(Panel(summary, title="Summary", border_style=style))


def print_config_table(rows: list[tuple[str, str]]) -> None:
    if not is_pretty():
        for key, value in rows:
            print(f"{key}: {value}")
        return

    table = Table(title="Current Config", show_header=True, header_style="bold cyan")
    table.add_column("Field", style="cyan", no_wrap=True)
    table.add_column("Value")
    for key, value in rows:
        table.add_row(key, value)
    console.print(table)


def print_update_summary(*, current_version: str, command: list[str], dry_run: bool) -> None:
    selected_command = " ".join(command)
    if not is_pretty():
        print(f"Current version: {current_version}")
        print(f"Selected command: {selected_command}")
        return

    table = Table(show_header=False, box=None)
    table.add_column("Field", style="cyan", no_wrap=True)
    table.add_column("Value")
    table.add_row("Current version", current_version)
    table.add_row("Selected command", selected_command)
    table.add_row("Mode", "dry run" if dry_run else "execute")
    console.print(Panel(table, title="Update", border_style="cyan"))


def print_chat_welcome(*, model: str, model_source: str) -> None:
    message = (
        "[bold cyan]cli-demo chat[/]\n"
        "A lightweight interactive AI session\n\n"
        f"[cyan]Model[/]: {model} ({model_source})\n"
        "[dim]Type /help for commands, /exit to quit.[/]"
    )
    if is_pretty():
        console.print(Panel(message, title="AI Chat", border_style="cyan", padding=(1, 2)))
        return

    print(f"cli-demo chat\nModel: {model} ({model_source})\nType /help for commands, /exit to quit.")


def chat_input() -> str:
    if is_pretty():
        return console.input("[bold cyan]>[/] ")
    return input("> ")


def print_chat_help() -> None:
    commands = [
        ("/help", "Show this help message."),
        ("/clear", "Clear in-memory chat history."),
        ("/history", "Show recent prompts and response snippets."),
        ("/retry", "Retry the last user prompt."),
        ("/model", "Show the current effective model."),
        ("/exit", "Quit the chat session."),
        ("/quit", "Quit the chat session."),
    ]
    if not is_pretty():
        print("Available commands:")
        for command, description in commands:
            print(f"  {command:<8} {description}")
        return

    table = Table(title="Chat Commands", show_header=True, header_style="bold cyan")
    table.add_column("Command", style="cyan", no_wrap=True)
    table.add_column("Description")
    for command, description in commands:
        table.add_row(command, description)
    console.print(table)


def print_chat_history(history: list[tuple[str, str]], *, limit: int = 5) -> None:
    if not history:
        print_warning("No chat history yet.")
        return

    visible = history[-limit:]
    if not is_pretty():
        start = len(history) - len(visible) + 1
        for index, (user_text, assistant_text) in enumerate(visible, start=start):
            print(f"{index}. {_snippet(user_text)}")
            print(f"   {_snippet(assistant_text)}")
        return

    table = Table(title=f"Recent History ({len(history)} exchange(s))", show_header=True, header_style="bold cyan")
    table.add_column("#", style="cyan", no_wrap=True)
    table.add_column("Prompt")
    table.add_column("Response")
    start = len(history) - len(visible) + 1
    for index, (user_text, assistant_text) in enumerate(visible, start=start):
        table.add_row(str(index), _snippet(user_text), _snippet(assistant_text))
    console.print(table)


def print_model_info(*, model: str, source: str) -> None:
    message = f"Current model: {model} ({source})"
    if is_pretty():
        console.print(Panel(message, title="Model", border_style="cyan"))
        return
    print(message)


def print_user_message(text: str) -> None:
    if not is_pretty():
        print(text)
        return

    console.print(
        Panel(
            Text(text),
            border_style="blue",
            padding=(0, 2),
        )
    )


def print_chat_response(text: str) -> None:
    if not is_pretty():
        print(text)
        return

    console.print(
        Panel(
            Markdown(text),
            border_style="green",
            padding=(1, 2),
        )
    )


def _status_text(status: Status) -> Text:
    styles = {
        "OK": "bold green",
        "WARN": "bold yellow",
        "FAIL": "bold red",
    }
    return Text(status, style=styles[status])


def _snippet(value: str, *, limit: int = 80) -> str:
    normalized = " ".join(value.split())
    if len(normalized) <= limit:
        return normalized
    return f"{normalized[: limit - 3]}..."
