"""bilge export - Export run data as Markdown or JSON."""

import json
from pathlib import Path

import typer
from rich.console import Console

from bilgeai.memory.store import ExperimentStore

console = Console()


def export_command(
    run_id: str = typer.Argument(None, help="Run ID to export (latest if omitted)"),
    format: str = typer.Option(
        "markdown",
        "--format",
        "-f",
        help="Export format: markdown, json, latex",
    ),
    output: Path = typer.Option(None, "--output", "-o", help="Output file path"),
) -> None:
    """Export a training run report as Markdown or JSON."""
    store = ExperimentStore()

    if run_id:
        record = store.get_run(run_id)
    else:
        runs = store.list_runs(limit=1)
        record = runs[0] if runs else None

    if record is None:
        console.print("[red]Run not found.[/red]")
        console.print("[yellow]Hint: Use 'bilge history' to list available runs.[/yellow]")
        raise typer.Exit(code=1)

    if format == "json":
        content = record.model_dump_json(indent=2)
    elif format == "latex":
        content = _render_latex(record)
    else:
        content = _render_markdown(record)

    if output:
        output.parent.mkdir(parents=True, exist_ok=True)
        output.write_text(content, encoding="utf-8")
        console.print(f"[green]Exported to {output}[/green]")
    else:
        console.print(content)


def _render_markdown(record) -> str:
    """Render a run record as Markdown."""
    config = json.loads(record.config_json)
    hardware = json.loads(record.hardware_json)

    lines = [
        f"# Training Run: {record.run_id}",
        "",
        f"- **Model**: {record.model_name}",
        f"- **Status**: {record.status}",
        f"- **Timestamp**: {record.timestamp}",
        f"- **Config Hash**: {record.config_hash}",
        "",
    ]

    # Results
    lines.append("## Results")
    lines.append("")
    if record.best_loss is not None:
        lines.append(f"- **Best Loss**: {record.best_loss:.4f}")
    if record.final_loss is not None:
        lines.append(f"- **Final Loss**: {record.final_loss:.4f}")
    if record.total_steps is not None:
        lines.append(f"- **Total Steps**: {record.total_steps}")
    if record.training_time_seconds is not None:
        lines.append(f"- **Training Time**: {record.training_time_seconds:.1f}s")
    if record.output_dir:
        lines.append(f"- **Output Dir**: {record.output_dir}")
    if not any([record.best_loss, record.final_loss, record.total_steps]):
        lines.append("_No results recorded yet._")
    lines.append("")

    # Config
    lines.append("## Training Config")
    lines.append("")
    lines.append("| Parameter | Value |")
    lines.append("|-----------|-------|")
    for key, value in sorted(config.items()):
        lines.append(f"| {key} | {value} |")
    lines.append("")

    # Hardware
    if hardware:
        lines.append("## Hardware")
        lines.append("")
        for key, value in sorted(hardware.items()):
            if not isinstance(value, (list, dict)):
                lines.append(f"- **{key}**: {value}")
        lines.append("")

    if record.notes:
        lines.append("## Notes")
        lines.append("")
        lines.append(record.notes)
        lines.append("")

    return "\n".join(lines)


def _render_latex(record) -> str:
    """Render a run record as a LaTeX table for academic papers."""
    config = json.loads(record.config_json)

    def _escape(val: str) -> str:
        """Escape special LaTeX characters."""
        for ch in ("_", "&", "%", "#", "{", "}"):
            val = val.replace(ch, f"\\{ch}")
        return val

    lines = [
        "% Generated by BilgeAI",
        f"% Run ID: {_escape(record.run_id)}",
        "",
        "\\begin{table}[h]",
        "\\centering",
        f"\\caption{{Training Configuration ({_escape(record.model_name)})}}",
        f"\\label{{tab:{record.run_id.replace('_', '-')}}}",
        "\\begin{tabular}{ll}",
        "\\toprule",
        "\\textbf{Parameter} & \\textbf{Value} \\\\",
        "\\midrule",
    ]

    for key, value in sorted(config.items()):
        lines.append(f"{_escape(str(key))} & {_escape(str(value))} \\\\")

    lines.extend(
        [
            "\\bottomrule",
            "\\end{tabular}",
        ]
    )

    # Results table if available
    has_results = any([record.best_loss, record.final_loss, record.total_steps])
    if has_results:
        lines.extend(
            [
                "\\vspace{0.5em}",
                "",
                "\\begin{tabular}{ll}",
                "\\toprule",
                "\\textbf{Metric} & \\textbf{Value} \\\\",
                "\\midrule",
            ]
        )
        if record.best_loss is not None:
            lines.append(f"Best Loss & {record.best_loss:.4f} \\\\")
        if record.final_loss is not None:
            lines.append(f"Final Loss & {record.final_loss:.4f} \\\\")
        if record.total_steps is not None:
            lines.append(f"Total Steps & {record.total_steps} \\\\")
        if record.training_time_seconds is not None:
            lines.append(f"Training Time (s) & {record.training_time_seconds:.1f} \\\\")
        lines.extend(
            [
                "\\bottomrule",
                "\\end{tabular}",
            ]
        )

    lines.extend(
        [
            "\\end{table}",
            "",
        ]
    )

    return "\n".join(lines)
