"""Output formatters for dead code violations."""

from __future__ import annotations

import json
from collections import defaultdict
from typing import TYPE_CHECKING

from rich.text import Text

if TYPE_CHECKING:
    from vibelexity.models import DeadCodeViolation


def dim(text: str) -> str:
    return f"[dim]{text}[/dim]"


def header(text: str) -> str:
    return f"[bold cyan]{text}[/bold cyan]"


def label(text: str) -> str:
    return f"[yellow]{text}[/yellow]"


def path(text: str) -> str:
    return f"[dim magenta]{text}[/dim magenta]"


def warn(text: str) -> str:
    return f"[bold red]{text}[/bold red]"


def format_json(violations: list[DeadCodeViolation]) -> str:
    if not violations:
        return json.dumps(
            {"total_violations": 0, "violations": [], "violations_by_type": {}}
        )

    violations_by_type = defaultdict(int)
    for v in violations:
        violations_by_type[v.type] += 1

    violations_json = []
    for v in violations:
        violations_json.append(
            {
                "type": v.type,
                "symbol": v.symbol,
                "location": v.location,
                "line": v.line,
                "confidence": v.confidence,
            }
        )

    output = {
        "total_violations": len(violations),
        "violations_by_type": dict(violations_by_type),
        "violations": violations_json,
    }

    return json.dumps(output, indent=2)


def format_text(violations: list[DeadCodeViolation]) -> str:
    if not violations:
        return dim("No dead code violations found.")

    violations_with_types = defaultdict(list)
    for v in violations:
        violations_with_types[v.type].append(v)

    type_names = {
        "unused_import": "Unused imports",
        "dead_function": "Dead functions",
        "dead_method": "Dead methods",
        "dead_class": "Dead classes",
        "unused_local_var": "Unused local variables",
    }

    if not violations:
        return dim("No dead code violations found.")

    max_loc_len = max(len(f"{v.location}:{v.line}") for v in violations)
    max_type_len = max(len(v.type) for v in violations)
    max_sym_len = max(len(str(v.symbol or "")) for v in violations)

    loc_width = max(max_loc_len, 40)
    type_width = max(max_type_len, 20)
    sym_width = max(max_sym_len, 30)

    lines = []
    lines.append(header(f"Dead code violations found: {len(violations)}"))
    lines.append("")

    for v_type in sorted(violations_with_types.keys()):
        category_violations = violations_with_types[v_type]
        category_name = type_names.get(v_type, v_type.replace("_", " ").title())
        lines.append(label(f"  {category_name}:"))

        if not category_violations:
            continue

        for v in category_violations:
            sym = v.symbol or ""
            loc_str = f"{v.location}:{v.line}"
            lines.append(
                f"    {path(loc_str):<{loc_width + 10}}  {warn(v.type):<{type_width + 10}}  {sym:<{sym_width}}  {dim(f'[{v.confidence}]')}"
            )

    return "\n".join(lines)
