# src/kontra/scout/reporters/markdown_reporter.py
"""
Markdown reporter for Kontra Scout - documentation-friendly output.
"""

from __future__ import annotations

from typing import List

from kontra.scout.types import DatasetProfile, ColumnProfile


def render_markdown(profile: DatasetProfile) -> str:
    """
    Render a DatasetProfile as Markdown.

    Returns Markdown string suitable for documentation or GitHub.
    """
    lines: List[str] = []

    # Header
    lines.append(f"# Data Profile: {profile.source_uri}")
    lines.append("")

    # Summary
    lines.append("## Summary")
    lines.append("")
    lines.append(f"- **Format:** {profile.source_format}")
    lines.append(f"- **Rows:** {profile.row_count:,}")
    lines.append(f"- **Columns:** {profile.column_count}")
    if profile.estimated_size_bytes:
        size_mb = profile.estimated_size_bytes / (1024 * 1024)
        lines.append(f"- **Size:** {size_mb:.1f} MB")
    if profile.sampled:
        lines.append(f"- **Sampled:** {profile.sample_size:,} rows")
    lines.append(f"- **Profiled at:** {profile.profiled_at}")
    lines.append(f"- **Duration:** {profile.profile_duration_ms} ms")
    lines.append("")

    # Schema table
    lines.append("## Schema")
    lines.append("")
    lines.append("| Column | Type | Nulls | Distinct | Cardinality |")
    lines.append("|--------|------|-------|----------|-------------|")

    # Check if this is a metadata-only preset (scout/lite)
    is_metadata_only = profile.preset in ("scout", "lite")

    for col in profile.columns:
        null_pct = f"{col.null_rate * 100:.1f}%"
        # Show "—" for distinct count if not computed (metadata-only preset)
        if is_metadata_only and col.distinct_count == 0:
            distinct = "—"
            card = "—"
        else:
            distinct = f"{col.distinct_count:,}"
            card = _cardinality_label(col)
        lines.append(f"| {col.name} | {col.dtype} | {null_pct} | {distinct} | {card} |")

    lines.append("")

    # Low cardinality columns (categorical)
    low_card_cols = [c for c in profile.columns if c.is_low_cardinality and c.values]
    if low_card_cols:
        lines.append("## Categorical Columns")
        lines.append("")
        for col in low_card_cols:
            lines.append(f"### {col.name}")
            lines.append("")
            if col.values:
                lines.append(f"**Values ({len(col.values)}):** `{', '.join(str(v) for v in col.values)}`")
            if col.top_values:
                lines.append("")
                lines.append("| Value | Count | % |")
                lines.append("|-------|-------|---|")
                for tv in col.top_values:
                    lines.append(f"| {tv.value} | {tv.count:,} | {tv.pct:.1f}% |")
            lines.append("")

    # Numeric columns
    numeric_cols = [c for c in profile.columns if c.numeric]
    if numeric_cols:
        lines.append("## Numeric Columns")
        lines.append("")
        lines.append("| Column | Min | Max | Mean | Median | Std |")
        lines.append("|--------|-----|-----|------|--------|-----|")
        for col in numeric_cols:
            n = col.numeric
            lines.append(
                f"| {col.name} | "
                f"{_fmt(n.min)} | {_fmt(n.max)} | "
                f"{_fmt(n.mean)} | {_fmt(n.median)} | {_fmt(n.std)} |"
            )
        lines.append("")

    # String columns
    string_cols = [c for c in profile.columns if c.string]
    if string_cols:
        lines.append("## String Columns")
        lines.append("")
        lines.append("| Column | Min Len | Max Len | Avg Len | Empty |")
        lines.append("|--------|---------|---------|---------|-------|")
        for col in string_cols:
            s = col.string
            lines.append(
                f"| {col.name} | "
                f"{s.min_length or 'N/A'} | {s.max_length or 'N/A'} | "
                f"{_fmt(s.avg_length)} | {s.empty_count:,} |"
            )
        lines.append("")

    # Temporal columns
    temporal_cols = [c for c in profile.columns if c.temporal]
    if temporal_cols:
        lines.append("## Temporal Columns")
        lines.append("")
        lines.append("| Column | Min Date | Max Date |")
        lines.append("|--------|----------|----------|")
        for col in temporal_cols:
            t = col.temporal
            lines.append(f"| {col.name} | {t.date_min or 'N/A'} | {t.date_max or 'N/A'} |")
        lines.append("")

    # Pattern detection
    pattern_cols = [c for c in profile.columns if c.detected_patterns]
    if pattern_cols:
        lines.append("## Detected Patterns")
        lines.append("")
        for col in pattern_cols:
            patterns = ", ".join(col.detected_patterns)
            lines.append(f"- **{col.name}:** {patterns}")
        lines.append("")

    # Footer - use preset name
    preset_title = profile.preset.title() if profile.preset else "Scout"
    lines.append("---")
    lines.append(f"*Generated by Kontra {preset_title} v{profile.engine_version}*")

    return "\n".join(lines)


def _cardinality_label(col: ColumnProfile) -> str:
    """Get cardinality label for a column."""
    if col.uniqueness_ratio >= 0.99 and col.null_rate == 0:
        return "unique"
    if col.is_low_cardinality:
        return "low"
    if col.distinct_count < 100:
        return "medium"
    return "high"


def _fmt(val: float | None) -> str:
    """Format a number for Markdown."""
    if val is None:
        return "N/A"
    if abs(val) >= 1000:
        return f"{val:,.0f}"
    if abs(val) >= 1:
        return f"{val:.2f}"
    return f"{val:.4f}"
