"""Read-only views of cached project context (rules, architecture, etc.)."""

from __future__ import annotations

import json
from pathlib import Path

import click

from ..display.output import console, info, warning, error, markdown, section_display
from ._cache import _is_cache_stale
from ._shared import get_repo_root, load_local_config


_REMOTE_HINT = "\n[dim]Connect to gjalla remote to get structured, filterable views of this data. Run [bold]gjalla connect[/bold].[/dim]"


def _cache_dir() -> tuple[Path, Path]:
    """Return (repo_root, cache_dir) or exit if not initialised."""
    repo_root = get_repo_root()
    cache = repo_root / ".gjalla" / "cache"
    return repo_root, cache


def _local_config(repo_root: Path) -> dict:
    """Load local config once for reuse within a command."""
    return load_local_config(repo_root) or {}


def _get_local_path(config: dict, key: str) -> str | None:
    """Return a local docs path from config by key, falling back to legacy local_docs_path."""
    return config.get(key) or config.get("local_docs_path")


def _no_docs_configured(kind: str) -> None:
    """Print a friendly message when no local docs path is configured."""
    info(f"No {kind} docs configured.")
    info("Run [bold]gjalla setup[/bold] to add a docs path, or [bold]gjalla connect[/bold] to link a remote project.")



def _print_local_docs(docs_path: str) -> None:
    """Print contents of local docs (file or directory)."""
    p = Path(docs_path)
    if not p.exists():
        error(f"Local docs path no longer exists: {docs_path}")
        info("Run [bold]gjalla setup[/bold] to update the path.")
        raise SystemExit(1)

    if p.is_file():
        content = p.read_text(encoding="utf-8")
        if p.suffix == ".md":
            markdown(content)
        else:
            console.print(content)
    elif p.is_dir():
        files = sorted(f for f in p.iterdir() if f.is_file() and not f.name.startswith("."))
        if not files:
            info(f"No files found in {docs_path}")
            return
        for f in files:
            console.print(f"[bold]── {f.name} ──[/bold]")
            content = f.read_text(encoding="utf-8")
            if f.suffix == ".md":
                markdown(content)
            else:
                console.print(content)
            console.print()
    console.print(_REMOTE_HINT)


def _check_cache(repo_root: Path, cache_dir: Path) -> bool:
    """Warn if cache is missing or stale.  Returns True if usable."""
    if not cache_dir.exists():
        error("No local cache. Run [bold]gjalla sync[/bold] first.")
        raise SystemExit(1)

    config = load_local_config(repo_root)
    stale = _is_cache_stale(config)
    if stale:
        warning("Cache may be stale. Run [bold]gjalla sync[/bold] to refresh.")
    return True


@click.group()
def show() -> None:
    """Show cached project context.

    \b
    Examples:
        gjalla show rules    # Display project rules
        gjalla show arch     # Display architecture overview
        gjalla show state    # Dump full cached state as JSON
    """


@show.command()
def rules() -> None:
    """Display project rules from the local cache."""
    repo_root, cache = _cache_dir()
    config = _local_config(repo_root)

    local_docs = _get_local_path(config, "local_rules_path")
    if local_docs:
        _print_local_docs(local_docs)
        return

    if not config.get("project_id"):
        _no_docs_configured("rules")
        return

    _check_cache(repo_root, cache)

    rules_file = cache / "rules.md"
    if not rules_file.exists():
        error("No rules cached. Run [bold]gjalla sync[/bold].")
        raise SystemExit(1)

    section_display("Project Rules", rules_file.read_text(encoding="utf-8"))


@show.command()
def arch() -> None:
    """Display architecture overview from the local cache."""
    repo_root, cache = _cache_dir()
    config = _local_config(repo_root)

    local_docs = _get_local_path(config, "local_arch_path")
    if local_docs:
        _print_local_docs(local_docs)
        return

    if not config.get("project_id"):
        _no_docs_configured("architecture")
        return

    _check_cache(repo_root, cache)

    arch_file = cache / "architecture.txt"
    if not arch_file.exists():
        error("No architecture cached. Run [bold]gjalla sync[/bold].")
        raise SystemExit(1)

    content = arch_file.read_text(encoding="utf-8")
    is_md = content.lstrip().startswith("#")
    section_display("Architecture Overview", content, color="blue", is_markdown=is_md)


@show.command()
def state() -> None:
    """Dump full cached project state as JSON."""
    repo_root, cache = _cache_dir()
    config = _local_config(repo_root)

    if not config.get("project_id"):
        info("No remote project linked. State requires a synced remote project.")
        info("Run [bold]gjalla connect[/bold] to link a project, then [bold]gjalla sync[/bold].")
        return

    _check_cache(repo_root, cache)

    state_file = cache / "state.json"
    if not state_file.exists():
        error("No state cached. Run [bold]gjalla sync[/bold].")
        raise SystemExit(1)

    data = json.loads(state_file.read_text(encoding="utf-8"))
    section_display("Project State", json.dumps(data, indent=2, default=str), color="green", is_markdown=False)


@show.command()
def capabilities() -> None:
    """Display project capabilities from the local cache."""
    repo_root, cache = _cache_dir()
    config = _local_config(repo_root)

    if not config.get("project_id"):
        info("No remote project linked. Capabilities requires a synced remote project.")
        info("Run [bold]gjalla connect[/bold] to link a project, then [bold]gjalla sync[/bold].")
        return

    _check_cache(repo_root, cache)

    state_file = cache / "state.json"
    if not state_file.exists():
        error("No state cached. Run [bold]gjalla sync[/bold].")
        raise SystemExit(1)

    data = json.loads(state_file.read_text(encoding="utf-8"))
    caps = data.get("capabilities", [])
    if not caps:
        info("No capabilities defined.")
        return

    lines = []
    for cap in caps:
        name = cap.get("name", "unnamed")
        desc = cap.get("description", "")
        suffix = f" — {desc}" if desc else ""
        lines.append(f"  [bold]{name}[/bold]{suffix}")
    section_display("Capabilities", "\n".join(lines), color="yellow", is_markdown=False, markup=True)
