from __future__ import annotations

from pathlib import Path
from typing import Annotated, List

import typer
import yaml

app = typer.Typer(add_completion=False, no_args_is_help=True, help="Scaffold runbooks")


def _normalize_name(name: str) -> str:
    n = name.strip()
    if n.endswith(".yaml") or n.endswith(".yml"):
        return n.rsplit(".", 1)[0]
    return n


def _book_path(name: str) -> Path:
    n = name.strip()
    p = Path(n)
    if p.suffix in (".yaml", ".yml") or "/" in n:
        return p.expanduser().resolve()
    return (Path("books") / f"{n}.yaml").resolve()


def _template_steps(kind: str) -> list[dict]:
    if kind == "release":
        return [
            {
                "name": "context",
                "desc": "Print execution context",
                "sh": ["bash", "-lc", "echo context ready"],
                "timeout": 30,
            },
            {
                "name": "validate",
                "desc": "Run preflight validation",
                "sh": ["bash", "-lc", "echo validating"],
                "timeout": 120,
            },
            {
                "name": "deploy",
                "desc": "Deploy changes",
                "sh": ["bash", "-lc", "echo deploying"],
                "timeout": 600,
                "on_fail": "halt",
            },
        ]
    if kind == "maintenance":
        return [
            {
                "name": "precheck",
                "desc": "Run maintenance prechecks",
                "sh": ["bash", "-lc", "echo precheck"],
                "timeout": 60,
            },
            {
                "name": "apply",
                "desc": "Apply maintenance operation",
                "sh": ["bash", "-lc", "echo applying maintenance"],
                "timeout": 300,
            },
            {
                "name": "postcheck",
                "desc": "Run postchecks",
                "sh": ["bash", "-lc", "echo postcheck"],
                "timeout": 60,
            },
        ]
    if kind == "audit":
        return [
            {
                "name": "collect",
                "desc": "Collect audit signals",
                "sh": ["bash", "-lc", "echo collecting audit data"],
                "timeout": 60,
            },
            {
                "name": "report",
                "desc": "Render audit report",
                "sh": ["bash", "-lc", "echo report complete"],
                "timeout": 60,
            },
        ]
    return [
        {
            "name": "step_one",
            "desc": "Describe your first step",
            "sh": ["bash", "-lc", "echo hello"],
            "timeout": 60,
        },
        {
            "name": "step_two",
            "desc": "Describe your second step",
            "sh": ["bash", "-lc", "echo world"],
            "timeout": 60,
        },
    ]


@app.command("book")
def init_book(
    name: Annotated[
        str, typer.Argument(help="Book name or path. Name creates books/<name>.yaml")
    ],
    title: Annotated[str, typer.Option("--title", help="Book title")] = "",
    description: Annotated[
        str, typer.Option("--description", help="Book description")
    ] = "",
    tag: Annotated[
        List[str], typer.Option("--tag", help="Tag value (repeatable)")
    ] = [],
    workspace: Annotated[
        str, typer.Option("--workspace", help="Default workspace var")
    ] = "dev",
    dir_value: Annotated[
        str, typer.Option("--dir", help="Default working directory var")
    ] = ".",
    template: Annotated[
        str,
        typer.Option(
            "--template", help="Template type: generic|release|maintenance|audit"
        ),
    ] = "generic",
    force: Annotated[
        bool, typer.Option("--force", help="Overwrite existing file")
    ] = False,
) -> None:
    if template not in ("generic", "release", "maintenance", "audit"):
        raise typer.BadParameter(
            "Invalid --template. Use generic, release, maintenance, or audit."
        )

    book_name = _normalize_name(name)
    path = _book_path(name)
    if path.exists() and not force:
        typer.echo(f"Refusing to overwrite existing file: {path}", err=True)
        raise typer.Exit(2)
    path.parent.mkdir(parents=True, exist_ok=True)

    data = {
        "kind": "pyplines.runbook.v1",
        "name": book_name,
        "title": title or book_name.replace("_", " ").title(),
        "description": description or "Describe this automation workflow.",
        "tags": tag,
        "inputs": {
            "workspace": {
                "type": "string",
                "description": "Workspace or environment name",
                "default": workspace,
            },
            "target_dir": {
                "type": "string",
                "description": "Target working directory",
                "default": dir_value,
            },
        },
        "packages": {"os": [], "py": []},
        "steps": _template_steps(template),
    }

    with open(path, "w", encoding="utf-8") as f:
        yaml.safe_dump(data, f, sort_keys=False, default_flow_style=False)

    typer.echo(f"Created: {path}")
