"""Shared CLI options with dynamic help text."""

from __future__ import annotations

from enum import Enum
from typing import TYPE_CHECKING

import typer

from .config import ConfigStore
from .exceptions import ConfigurationError

if TYPE_CHECKING:
    from typing import Any


class OutputMode(str, Enum):
    """Output format mode for CLI commands.

    Attributes:
        TEXT: Human-readable Rich console output (default).
        JSON: Machine-parseable JSON output.
    """

    TEXT = "text"
    JSON = "json"


class DynamicProjectHelp(str):
    """Help text that computes current project at render time.

    Inherits from str to satisfy Click/Typer's inspect.cleandoc() calls
    which expect string methods like expandtabs(). The actual help text
    is computed dynamically via __str__() when rendered.
    """

    def __new__(cls) -> DynamicProjectHelp:
        """Create instance with empty string base."""
        return super().__new__(cls, "")

    def __str__(self) -> str:
        """Return help text with current project status."""
        try:
            config = ConfigStore().load()
            project = config.default_project
            if project:
                return f"Project key (current: {project})"
            return "Project key (current: not set)"
        except (ConfigurationError, OSError, Exception):
            # Graceful degradation: help should always work
            return "Project key (current: unknown)"

    def expandtabs(self, tabsize: int = 8) -> str:
        """Return expanded help text (required by inspect.cleandoc)."""
        return str(self).expandtabs(tabsize)


def output_option(**kwargs: Any) -> Any:
    """Factory function for creating a global --output option.

    This returns a typer.Option for specifying output format (text or json).

    Args:
        **kwargs: Additional keyword arguments passed to typer.Option.

    Returns:
        A typer.Option configured for output mode selection.

    Example:
        @app.callback()
        def main(
            output: OutputMode = output_option(),
        ) -> None:
            ...
    """
    option_kwargs = {
        "help": "Output format: 'text' (default) or 'json' for machine-parseable output.",
        **kwargs,
    }
    return typer.Option(OutputMode.TEXT, "--output", "-o", **option_kwargs)


def json_option(**kwargs: Any) -> Any:
    """Factory function for creating a --json flag.

    This returns a typer.Option for outputting results in JSON format.

    Note:
        This is maintained for backwards compatibility. New commands should
        use the global --output option instead.

    Args:
        **kwargs: Additional keyword arguments passed to typer.Option.

    Returns:
        A typer.Option configured for JSON output mode.

    Example:
        @app.command()
        def my_command(
            json_output: bool = json_option(),
        ) -> None:
            ...
    """
    option_kwargs = {
        "help": "Output results in JSON format.",
        **kwargs,
    }
    return typer.Option(False, "--json", **option_kwargs)


def project_option(**kwargs: Any) -> Any:
    """Factory function for creating a --project option with dynamic help.

    This returns a typer.Option with help text that dynamically shows the
    current default project when --help is invoked.

    Args:
        **kwargs: Additional keyword arguments passed to typer.Option.
            Common overrides: envvar, show_default, etc.

    Returns:
        A typer.Option configured with dynamic project help text.

    Example:
        @app.command()
        def my_command(
            project: str = project_option(),
        ) -> None:
            ...
    """
    # Merge defaults with any overrides
    option_kwargs = {
        "help": DynamicProjectHelp(),
        **kwargs,
    }
    return typer.Option(None, "--project", "-p", **option_kwargs)
