"""CLI entry point for agentreflect."""

import sys
from pathlib import Path
from typing import Optional

import click

from . import __version__
from .parsers import PytestParser, GitLogParser, NotesParser
from .generators import PatternGenerator
from .models import FailureRecord


@click.group()
@click.version_option(version=__version__, prog_name="agentreflect")
def cli():
    """agentreflect — generate AGENTS.md rules from agent failure logs.

    Analyze AI coding agent failures and get targeted rule suggestions
    to prevent recurrence. Part of the agent quality trilogy:
    coderace → agentmd → agentlint → agentreflect.
    """


@cli.command()
@click.option(
    "--from-pytest",
    "pytest_file",
    type=click.Path(exists=True),
    default=None,
    help="Path to pytest output file (e.g. captured with `pytest ... 2>&1 | tee failures.txt`)",
)
@click.option(
    "--from-git",
    "from_git",
    is_flag=True,
    default=False,
    help="Analyze git log of current directory for fix/bug/revert commits",
)
@click.option(
    "--from-notes",
    "notes",
    default=None,
    help="Plain text description of what went wrong (quoted string)",
)
@click.option(
    "--llm",
    "use_llm",
    is_flag=True,
    default=False,
    help="Use Anthropic API for enhanced analysis (requires ANTHROPIC_API_KEY)",
)
@click.option(
    "--format",
    "output_format",
    type=click.Choice(["markdown", "diff"]),
    default="markdown",
    show_default=True,
    help="Output format",
)
@click.option(
    "--apply",
    "apply_file",
    type=click.Path(),
    default=None,
    help="Apply suggestions directly to an AGENTS.md file",
)
@click.option(
    "--yes",
    "-y",
    is_flag=True,
    default=False,
    help="Skip confirmation when applying to file",
)
@click.option(
    "--min-confidence",
    type=float,
    default=0.0,
    help="Minimum confidence threshold for suggestions (0.0–1.0)",
)
@click.option(
    "--ci",
    "ci_mode",
    is_flag=True,
    default=False,
    help="CI mode: write JSON to stdout, summary to stderr",
)
@click.option(
    "--fail-on",
    "fail_on",
    type=int,
    default=0,
    help="Exit code 1 if rules_generated >= N (0 = never fail)",
)
def generate(
    pytest_file: Optional[str],
    from_git: bool,
    notes: Optional[str],
    use_llm: bool,
    output_format: str,
    apply_file: Optional[str],
    yes: bool,
    min_confidence: float,
    ci_mode: bool,
    fail_on: int,
):
    """Generate AGENTS.md rule suggestions from failure logs."""

    if not any([pytest_file, from_git, notes]):
        raise click.UsageError(
            "At least one input is required: --from-pytest, --from-git, or --from-notes"
        )

    all_records: list[FailureRecord] = []
    source_labels = []

    # Parse inputs
    if pytest_file:
        content = Path(pytest_file).read_text(encoding="utf-8")
        parser = PytestParser()
        records = parser.parse(content)
        all_records.extend(records)
        source_labels.append(f"pytest failures ({pytest_file})")
        if not records:
            click.echo(
                f"[warn] No failures found in {pytest_file}. "
                "Make sure the file contains pytest output with FAILED/ERROR lines.",
                err=True,
            )

    if from_git:
        records = GitLogParser.from_repo(".")
        all_records.extend(records)
        source_labels.append("git log")
        if not records:
            click.echo(
                "[info] No fix/bug/revert commits found in git log.",
                err=True,
            )

    if notes:
        parser = NotesParser()
        records = parser.parse(notes)
        all_records.extend(records)
        source_labels.append("notes")

    # Generate suggestions
    if use_llm:
        from .generators.llm_generator import generate_with_llm

        agents_content = None
        if apply_file and Path(apply_file).exists():
            agents_content = Path(apply_file).read_text(encoding="utf-8")

        try:
            suggestions = generate_with_llm(all_records, agents_content)
        except (ImportError, ValueError) as e:
            click.echo(f"[error] LLM mode failed: {e}", err=True)
            click.echo("[info] Falling back to pattern-based analysis.", err=True)
            suggestions = PatternGenerator().generate(all_records)
    else:
        suggestions = PatternGenerator().generate(all_records)

    # Filter by confidence
    if min_confidence > 0:
        suggestions = [s for s in suggestions if s.confidence >= min_confidence]

    source_label = " + ".join(source_labels)

    # CI mode output
    if ci_mode:
        import json as _json
        rules_count = len(suggestions)
        ci_output = {
            "ci": True,
            "rules_count": rules_count,
            "rules_generated": rules_count,
            "source": source_label,
            "suggestions": [
                {
                    "rule": s.text,
                    "rationale": getattr(s, "rationale", s.source or ""),
                    "confidence": s.confidence,
                    "category": s.category,
                }
                for s in suggestions
            ],
        }
        click.echo(_json.dumps(ci_output, indent=2))
        click.echo(
            f"[agentreflect] {rules_count} rule(s) generated from {source_label}",
            err=True,
        )
        if fail_on > 0 and rules_count >= fail_on:
            click.echo(
                f"[agentreflect] FAIL: {rules_count} rules >= threshold {fail_on}",
                err=True,
            )
            sys.exit(1)
        return

    # Output
    if apply_file:
        from .output.apply import apply_to_file

        apply_to_file(suggestions, apply_file, yes=yes, echo=click.echo)
    elif output_format == "diff":
        from .output.diff_formatter import format_diff

        existing = None
        if Path("AGENTS.md").exists():
            existing = Path("AGENTS.md").read_text(encoding="utf-8")

        click.echo(format_diff(suggestions, "AGENTS.md", existing), nl=False)
    else:
        from .output.markdown_formatter import format_markdown

        click.echo(format_markdown(suggestions, all_records, source_label), nl=False)
