"""Output formatters — JSON and human-readable."""

import json
import sys


def format_search_results(data: dict, fmt: str = "json") -> str:
    """Format search results for output."""
    if fmt == "json":
        return json.dumps(data, indent=2, ensure_ascii=False)
    return _human_search(data)


def _human_search(data: dict) -> str:
    """Human-readable search output."""
    lines = []
    total = data["total_matches"]
    returned = data["returned"]
    lines.append(f'Search: "{data["query"]}" ({total} matches, showing top {returned})')
    lines.append("")

    for i, r in enumerate(data["results"], 1):
        src = r["source"]
        score = r["score"]

        # Title with page/section
        location = ""
        if src.get("page"):
            location = f" (p.{src['page']})"
        elif src.get("section_header"):
            location = f" \u00a7{src['section_header']}"

        # Tags
        tag_str = ""
        if src.get("tags"):
            tag_str = " [" + ", ".join(src["tags"]) + "]"

        lines.append(f" {i:2d}. [{score:.3f}] {src['title']}{location}  [{src['type']}]{tag_str}")

        # Text preview (first 200 chars)
        preview = r["text"][:200].replace("\n", " ").strip()
        if len(r["text"]) > 200:
            preview += "..."
        lines.append(f"     {preview}")
        lines.append("")

    return "\n".join(lines)


def format_document_list(docs: list[dict], fmt: str = "json") -> str:
    """Format document list."""
    if fmt == "json":
        return json.dumps(docs, indent=2, ensure_ascii=False)
    return _human_doc_list(docs)


def _human_doc_list(docs: list[dict]) -> str:
    """Human-readable document list."""
    if not docs:
        return "No documents indexed. Run `kb add` to get started."

    lines = [f"{'ID':>5}  {'Type':<10} {'Chunks':>6}  {'Title':<40}  {'Tags'}"]
    lines.append("-" * 80)

    for d in docs:
        tags = ", ".join(d.get("tags", []))
        title = d["title"][:40]
        lines.append(f"{d['id']:>5}  {d['type']:<10} {d['chunk_count']:>6}  {title:<40}  {tags}")

    return "\n".join(lines)


def format_tags(tags: list[dict], fmt: str = "json") -> str:
    """Format tag list."""
    if fmt == "json":
        return json.dumps(tags, indent=2, ensure_ascii=False)

    if not tags:
        return "No tags. Use `kb add --tags` or `kb tag` to add tags."

    lines = [f"{'Tag':<30} {'Documents':>10}"]
    lines.append("-" * 42)
    for t in tags:
        lines.append(f"{t['name']:<30} {t['count']:>10}")
    return "\n".join(lines)


def format_doc_info(info: dict, fmt: str = "json") -> str:
    """Format document info."""
    if fmt == "json":
        return json.dumps(info, indent=2, ensure_ascii=False)

    lines = []
    lines.append(f"Document #{info['id']}: {info['title']}")
    lines.append(f"  Type:    {info['type']}")
    if info.get("language"):
        lines.append(f"  Language: {info['language']}")
    if info.get("path"):
        lines.append(f"  Path:    {info['path']}")
    lines.append(f"  Hash:    {info['content_hash']}")
    lines.append(f"  Created: {info['created_at']}")
    if info.get("tags"):
        lines.append(f"  Tags:    {', '.join(info['tags'])}")
    lines.append(f"  Chunks:  {info['chunk_count']}")
    lines.append("")

    for chunk in info.get("chunks", []):
        preview = chunk["text"][:100].replace("\n", " ").strip()
        if len(chunk["text"]) > 100:
            preview += "..."
        lines.append(f"  [{chunk['chunk_index']}] {preview}")

    return "\n".join(lines)


def format_status(status: dict, fmt: str = "json") -> str:
    """Format status output."""
    if fmt == "json":
        return json.dumps(status, indent=2, ensure_ascii=False)

    lines = []
    lines.append("Knowledge Base Status")
    lines.append("=" * 40)
    lines.append(f"  Model:          {status['model_name']}")
    lines.append(f"  Embedding dim:  {status['embedding_dim']}")
    lines.append(f"  Schema version: {status['schema_version']}")
    lines.append(f"  DB size:        {_human_size(status['db_size_bytes'])}")
    lines.append("")
    lines.append("  Documents:")
    for dtype, count in status.get("documents", {}).items():
        lines.append(f"    {dtype:<12} {count:>5}")
    lines.append(f"    {'total':<12} {status['total_documents']:>5}")
    lines.append(f"  Total chunks:   {status['total_chunks']}")

    return "\n".join(lines)


def _human_size(size_bytes: int) -> str:
    """Format bytes as human-readable."""
    for unit in ("B", "KB", "MB", "GB"):
        if size_bytes < 1024:
            return f"{size_bytes:.1f} {unit}"
        size_bytes /= 1024
    return f"{size_bytes:.1f} TB"
