"""releaseops bundle — Create, inspect, and manage bundles."""

from typing import List, Optional

import typer
import yaml

from llmhq_releaseops.core.bundler import Bundler
from llmhq_releaseops.models.artifact import ArtifactRef, ArtifactType
from llmhq_releaseops.models.bundle import ModelConfig
from llmhq_releaseops.storage.git_store import GitStore

app = typer.Typer(help="Create, inspect, and manage bundles.")


def _get_bundler(path: str = ".") -> Bundler:
    store = GitStore(path)
    if not store.is_initialized():
        typer.echo("Error: ReleaseOps not initialized. Run 'releaseops init' first.", err=True)
        raise typer.Exit(1)
    return Bundler(store)


def _parse_artifact(spec: str) -> tuple:
    """Parse 'role=prompt_id:version' into (role, prompt_id, version)."""
    if "=" not in spec:
        raise typer.BadParameter(f"Invalid artifact spec '{spec}'. Use role=prompt_id:version")
    role, ref = spec.split("=", 1)
    if ":" in ref:
        prompt_id, version = ref.split(":", 1)
    else:
        prompt_id, version = ref, None
    return role.strip(), prompt_id.strip(), version.strip() if version else None


def _parse_policy(spec: str) -> tuple:
    """Parse 'role=path' into (role, path)."""
    if "=" not in spec:
        raise typer.BadParameter(f"Invalid policy spec '{spec}'. Use role=path/to/policy.yaml")
    role, path = spec.split("=", 1)
    return role.strip(), path.strip()


@app.command()
def create(
    name: str = typer.Argument(..., help="Bundle identifier (e.g., support-agent)"),
    version: str = typer.Option("1.0.0", "--version", "-v", help="Bundle version"),
    artifact: Optional[List[str]] = typer.Option(None, "--artifact", "-a", help="Prompt artifact: role=prompt_id:version"),
    policy: Optional[List[str]] = typer.Option(None, "--policy", help="Policy: role=path/to/policy.yaml"),
    model: Optional[str] = typer.Option(None, "--model", "-m", help="Model ID (e.g., claude-sonnet-4-5-20250929)"),
    provider: str = typer.Option("anthropic", "--provider", help="Model provider"),
    temperature: float = typer.Option(0.7, "--temperature", "-t", help="Model temperature"),
    description: str = typer.Option("", "--description", "-d", help="Bundle description"),
    path: str = typer.Option(".", "--path", help="Repository root path"),
):
    """Create a new bundle from prompts, policies, and model config."""
    bundler = _get_bundler(path)

    # Parse prompt artifacts
    prompts = {}
    if artifact:
        from llmhq_releaseops.integration.prompt_bridge import PromptBridge

        bridge = PromptBridge(path)
        for spec in artifact:
            role, prompt_id, ver = _parse_artifact(spec)
            try:
                ref = bridge.create_artifact_ref(role, prompt_id, ver)
                prompts[role] = ref
            except Exception as e:
                typer.echo(f"Error resolving artifact '{spec}': {e}", err=True)
                raise typer.Exit(1)

    # Parse policy artifacts
    policies = {}
    if policy:
        policy_type_map = {
            "context": ArtifactType.POLICY_CONTEXT,
            "tools": ArtifactType.POLICY_TOOLS,
            "safety": ArtifactType.POLICY_SAFETY,
        }
        for spec in policy:
            role, policy_path = _parse_policy(spec)
            art_type = policy_type_map.get(role, ArtifactType.POLICY_CONTEXT)
            policies[role] = ArtifactRef(
                artifact_type=art_type,
                role=role,
                path=policy_path,
            )

    # Model config
    model_config = None
    if model:
        model_config = ModelConfig(
            provider=provider,
            model=model,
            temperature=temperature,
        )

    bundle = bundler.create(
        bundle_id=name,
        version=version,
        prompts=prompts,
        policies=policies,
        model_config=model_config,
        description=description,
        created_by="cli",
    )
    typer.echo(f"Created bundle: {bundle.id} v{bundle.version}")
    typer.echo(f"  Hash: {bundle.bundle_hash}")
    typer.echo(f"  Artifacts: {len(bundle.all_artifacts)}")


@app.command("list")
def list_bundles(
    path: str = typer.Option(".", "--path", help="Repository root path"),
):
    """List all bundles."""
    bundler = _get_bundler(path)
    bundles = bundler.list_bundles()
    if not bundles:
        typer.echo("No bundles found.")
        return
    for bid in bundles:
        versions = bundler.list_versions(bid)
        typer.echo(f"  {bid} ({len(versions)} version(s): {', '.join(versions)})")


@app.command()
def inspect(
    bundle_id: str = typer.Argument(..., help="Bundle ID"),
    version: Optional[str] = typer.Option(None, "--version", "-v", help="Version (default: latest)"),
    path: str = typer.Option(".", "--path", help="Repository root path"),
):
    """Show detailed bundle manifest."""
    bundler = _get_bundler(path)
    if version is None:
        versions = bundler.list_versions(bundle_id)
        if not versions:
            typer.echo(f"No versions found for '{bundle_id}'.", err=True)
            raise typer.Exit(1)
        version = versions[-1]

    info = bundler.inspect(bundle_id, version)
    typer.echo(yaml.dump(info, default_flow_style=False, sort_keys=False))


@app.command()
def verify(
    bundle_id: str = typer.Argument(..., help="Bundle ID"),
    version: Optional[str] = typer.Option(None, "--version", "-v", help="Version"),
    path: str = typer.Option(".", "--path", help="Repository root path"),
):
    """Verify bundle integrity by checking content hashes."""
    bundler = _get_bundler(path)
    if version is None:
        versions = bundler.list_versions(bundle_id)
        if not versions:
            typer.echo(f"No versions found for '{bundle_id}'.", err=True)
            raise typer.Exit(1)
        version = versions[-1]

    errors = bundler.verify(bundle_id, version)
    if errors:
        typer.echo(f"FAILED — {len(errors)} error(s):", err=True)
        for e in errors:
            typer.echo(f"  - {e}", err=True)
        raise typer.Exit(1)
    else:
        typer.echo(f"OK — {bundle_id} v{version} integrity verified.")


@app.command()
def diff(
    bundle_id: str = typer.Argument(..., help="Bundle ID"),
    version1: str = typer.Argument(..., help="First version"),
    version2: str = typer.Argument(..., help="Second version"),
    path: str = typer.Option(".", "--path", help="Repository root path"),
):
    """Compare two versions of a bundle."""
    bundler = _get_bundler(path)
    result = bundler.diff(bundle_id, version1, version2)
    typer.echo(f"Diff: {bundle_id} {version1} → {version2}")
    for section in ("prompts", "policies"):
        d = result[section]
        if d["added"]:
            typer.echo(f"  {section} added: {', '.join(d['added'])}")
        if d["removed"]:
            typer.echo(f"  {section} removed: {', '.join(d['removed'])}")
        if d["changed"]:
            typer.echo(f"  {section} changed: {', '.join(d['changed'])}")
        if d["unchanged"]:
            typer.echo(f"  {section} unchanged: {', '.join(d['unchanged'])}")
    if result["model_config_changed"]:
        typer.echo("  model_config: changed")
