"""CLI commands for Rhiza Tools.

This module defines the main Typer application and all command-line interface
commands for rhiza-tools. It provides commands for version bumping, coverage
badge generation, release management, and README updates.

The CLI can be used either as a standalone tool (`rhiza-tools`) or as a
subcommand of the rhiza CLI (`rhiza tools`).

Example:
    Bump version to a specific version::

        $ rhiza-tools bump 1.2.3
        $ rhiza tools bump 1.2.3

    Bump version interactively::

        $ rhiza-tools bump

    Generate a coverage badge::

        $ rhiza-tools generate-coverage-badge --coverage-json _tests/coverage.json

    Update README with make help output::

        $ rhiza-tools update-readme
"""

from pathlib import Path

import typer

from rhiza_tools import __version__

from .commands.bump import bump_command
from .commands.generate_badge import generate_coverage_badge_command
from .commands.update_readme import update_readme_command


def version_callback(value: bool):
    """Display the version and exit."""
    if value:
        typer.echo(f"rhiza-tools version {__version__}")
        raise typer.Exit()


app = typer.Typer(help="Rhiza Tools - Extra utilities for Rhiza.")


@app.callback()
def main(
    version: bool = typer.Option(
        None,
        "--version",
        help="Show the version and exit.",
        callback=version_callback,
        is_eager=True,
    ),
):
    """Rhiza Tools - Extra utilities for Rhiza."""
    pass


@app.command()
def bump(
    version: str | None = typer.Argument(None, help="The version to bump to (e.g., 1.0.1, major, minor, patch, etc)"),
    dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."),
    commit: bool = typer.Option(False, "--commit", help="Commit the changes to git."),
    allow_dirty: bool = typer.Option(
        False, "--allow-dirty", help="Allow bumping even if the working directory is dirty."
    ),
    verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed output from bump-my-version."),
):
    """Bump the version of the project.

    This command updates the version in pyproject.toml using semantic versioning.
    You can provide an explicit version number, a bump type (patch, minor, major),
    or leave it blank for an interactive prompt.

    Args:
        version: The version to bump to. Can be an explicit version (e.g., "1.2.3"),
            a bump type ("patch", "minor", "major"), a prerelease type
            ("alpha", "beta", "rc", "dev"), or None for interactive selection.
        dry_run: If True, show what would change without actually changing anything.
        commit: If True, automatically commit the version change to git.
        allow_dirty: If True, allow bumping even with uncommitted changes.
        verbose: If True, show detailed output from the bump-my-version tool.

    Example:
        Bump to a specific version::

            $ rhiza-tools bump 2.0.0

        Bump patch version (1.2.3 -> 1.2.4)::

            $ rhiza-tools bump patch

        Preview changes without applying them::

            $ rhiza-tools bump minor --dry-run

        Interactive version selection::

            $ rhiza-tools bump
    """
    bump_command(version, dry_run, commit, allow_dirty, verbose)


@app.command()
def generate_coverage_badge(
    coverage_json: Path = typer.Option(
        Path("_tests/coverage.json"),
        "--coverage-json",
        help="Path to coverage.json file",
    ),
    output: Path = typer.Option(
        Path("_book/tests/coverage-badge.json"),
        help="Path to output badge JSON",
    ),
):
    """Generate a coverage badge for the project.

    Reads a coverage report JSON file and creates a shields.io endpoint JSON file
    for displaying a coverage badge. The badge color automatically adjusts based
    on the coverage percentage.

    Args:
        coverage_json: Path to the coverage.json file generated by pytest-cov.
        output: Path where the badge JSON file should be written.

    Example:
        Generate badge with default paths::

            $ rhiza-tools generate-coverage-badge

        Generate badge with custom paths::

            $ rhiza-tools generate-coverage-badge \
                --coverage-json tests/coverage.json \
                --output assets/badge.json
    """
    generate_coverage_badge_command(coverage_json_path=coverage_json, output_path=output)


@app.command()
def release(
    dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."),
):
    """Create a git tag and push to remote to trigger the release workflow.

    This command creates a git tag based on the current version and pushes it
    to the remote repository, which triggers the automated release workflow.

    Args:
        dry_run: If True, show what would happen without actually creating or
            pushing the tag.

    Example:
        Create and push a release tag::

            $ rhiza-tools release

        Preview what would happen::

            $ rhiza-tools release --dry-run
    """
    if dry_run:
        typer.echo("Would create and push release tag")
    else:
        typer.echo("Creating and pushing release tag")
        # Implement actual release logic here (port from release.sh)


@app.command(name="update-readme")
def update_readme(
    dry_run: bool = typer.Option(False, "--dry-run", help="Print what would happen without doing it."),
):
    """Update README.md with the current output from `make help`.

    This command runs `make help` and updates the README.md file with the current
    help output, keeping the documentation in sync with available Make targets.

    Args:
        dry_run: If True, show the help output that would be inserted without
            actually modifying README.md.

    Example:
        Update README with make help output::

            $ rhiza-tools update-readme

        Preview changes without modifying README::

            $ rhiza-tools update-readme --dry-run
    """
    update_readme_command(dry_run)
