"""CLI entry point for primust-discover."""

from __future__ import annotations

import json
import os
import sys


def _post_session(detected: dict, generated: dict) -> str | None:
    """Post scan results as a setup session token. Returns session_id or None."""
    try:
        import httpx

        endpoint = os.environ.get(
            "PRIMUST_API_URL", "https://primust-api.fly.dev/api/v1"
        )
        res = httpx.post(
            f"{endpoint}/setup/sessions",
            json={"detected": detected, "generated": generated},
            timeout=5.0,
        )
        if res.status_code == 200:
            return res.json().get("session_id")
    except Exception:
        pass
    return None


def _find_entry_points(root: str) -> list[str]:
    """Find Python files with main() or if __name__ == '__main__'."""
    from pathlib import Path

    entries = []
    root_path = Path(root)
    skip = {"node_modules", ".git", "__pycache__", ".venv", "venv", "dist", "build"}

    for py_file in root_path.rglob("*.py"):
        if any(part in skip for part in py_file.parts):
            continue
        try:
            text = py_file.read_text(errors="ignore")
            if 'if __name__ ==' in text or "def main(" in text or "async def main(" in text:
                entries.append(str(py_file.relative_to(root_path)))
        except Exception:
            continue
    return entries


def _build_ai_prompt(detected: dict) -> str:
    """Build the AI coding assistant prompt from detected frameworks."""
    key_placeholder = os.environ.get("PRIMUST_API_KEY", "pk_sb_YOUR_KEY")
    install_cmd = detected.get("install_command", 'pip install "primust[langgraph]"')

    return f"""Add Primust governance to this codebase.

Step 1 — Add to your .env file:
PRIMUST_API_KEY={key_placeholder}

Step 2 — Install:
{install_cmd}

Step 3 — Find where the main agent or pipeline is initialized and add
these three lines immediately before it runs:

from primust.adapters import autoinstrument
import primust

p = primust.Pipeline()
autoinstrument(pipeline=p)

Rules:
- Do not add p.record() anywhere
- Do not restructure the agent or pipeline
- Do not move existing logic
- Just add the three lines in the right place
- If there are multiple agents or entry points, add to each one separately

That is the entire integration."""


def main() -> None:
    import argparse

    parser = argparse.ArgumentParser(
        prog="primust-discover",
        description="Discover governance decision points in a Python codebase via static analysis.",
    )
    parser.add_argument("path", help="Path to codebase root")
    parser.add_argument(
        "--output",
        default=None,
        help="Directory for generated manifest stubs (default: no manifest generation)",
    )
    parser.add_argument(
        "--json",
        action="store_true",
        dest="json_output",
        help="Output as JSON instead of formatted report",
    )
    parser.add_argument(
        "--no-session",
        action="store_true",
        help="Don't post scan results as a session token",
    )
    args = parser.parse_args()

    from primust_discover.analyzer import discover, format_report

    try:
        report = discover(root_path=args.path, output_dir=args.output)
    except FileNotFoundError as e:
        print(f"Error: {e}", file=sys.stderr)
        sys.exit(1)

    if args.json_output:
        data = {
            "root_path": report.root_path,
            "files_analyzed": report.files_analyzed,
            "lines_analyzed": report.lines_analyzed,
            "decision_points_count": report.count,
            "decision_points": [
                {
                    "file": dp.file,
                    "line": dp.line,
                    "function_name": dp.function_name,
                    "pattern": dp.pattern.name,
                    "proof_level": dp.pattern.proof_level,
                    "category": dp.pattern.category,
                    "suggested_manifest_id": dp.suggested_manifest_id,
                }
                for dp in report.decision_points
            ],
            "manifests_generated": report.manifests_generated,
        }
        print(json.dumps(data, indent=2))
    else:
        print(format_report(report))

    # Post session token after report
    if not args.no_session:
        # Extract detected frameworks from decision points
        framework_set = set()
        model_set = set()
        for dp in report.decision_points:
            cat = dp.pattern.category.lower()
            if "framework" in cat:
                framework_set.add(dp.pattern.name.lower())
            elif "model" in cat or "ml" in cat:
                model_set.add(dp.pattern.name.lower())

        frameworks = sorted(framework_set) or ["unknown"]
        models = sorted(model_set)
        entry_points = _find_entry_points(args.path)

        # Build install command from detected frameworks
        extras = []
        framework_to_extra = {
            "langgraph": "langgraph",
            "openai_agents": "openai-agents",
            "google_adk": "google-adk",
            "crewai": "crewai",
            "pydantic_ai": "pydantic-ai",
            "semantic_kernel": "semantic-kernel",
            "opentelemetry": "otel",
        }
        for fw in frameworks:
            for key, extra in framework_to_extra.items():
                if key in fw:
                    extras.append(extra)
                    break
        if not extras:
            extras = ["langgraph"]
        install_command = f'pip install "primust[{",".join(extras)}]"'

        # Compute projected provable surface
        by_level = report.by_proof_level()
        total = report.count or 1
        math_count = len(by_level.get("mathematical", []))
        provable_surface = round(math_count / total, 2) if total > 0 else 0.0

        detected = {
            "frameworks": frameworks,
            "models": models,
            "entry_points": entry_points,
            "install_command": install_command,
            "projected_provable_surface": provable_surface,
        }

        key_placeholder = os.environ.get("PRIMUST_API_KEY", "placeholder")
        generated = {
            "env_line": f"PRIMUST_API_KEY={key_placeholder}",
            "install": install_command,
            "code": "from primust.adapters import autoinstrument\nimport primust\n\np = primust.Pipeline()\nautoinstrument(pipeline=p)",
            "ai_prompt": _build_ai_prompt(detected),
        }

        session_id = _post_session(detected, generated)

        if session_id:
            print(f"""
Ready to instrument? Sign up and your setup will be ready to run:
https://primust.com/signup?session={session_id}

Results waiting for 30 minutes.
Already have an account? https://app.primust.com/setup?session={session_id}
""")


if __name__ == "__main__":
    main()
