from pathlib import Path
from typing import Annotated, Any

import typer
from pydantic import BaseModel, Field
from rich_toolkit import RichToolkit
from rich_toolkit.menu import Option

from fastapi_cloud_cli.api import APIClient
from fastapi_cloud_cli.commands._auth import UserCommand, get_user_command_context
from fastapi_cloud_cli.commands.env._app import env_app
from fastapi_cloud_cli.utils.apps import resolve_app_id_or_fail
from fastapi_cloud_cli.utils.env import validate_environment_variable_name
from fastapi_cloud_cli.utils.execution import JsonOutputOption


class EnvironmentVariableDeleteOutput(BaseModel):
    app_id: str
    name: str
    deleted: bool = True
    show_tag: Annotated[bool, Field(exclude=True)] = True


def _render_environment_variable_delete_output(
    data: EnvironmentVariableDeleteOutput, toolkit: RichToolkit
) -> None:
    if data.show_tag:
        toolkit.print_title("environment variables")

    toolkit.print_line()
    toolkit.print(f"Environment variable [bold]{data.name}[/] deleted.", bullet=False)


@env_app.command(cls=UserCommand)
def delete(
    ctx: typer.Context,
    name: str | None = typer.Argument(
        None,
        help="The name of the environment variable to delete",
    ),
    path_arg: Annotated[
        Path | None,
        typer.Argument(
            help=(
                "Path to the directory with your app's pyproject.toml "
                "(defaults to current directory)"
            ),
        ),
    ] = None,
    path: Annotated[
        Path | None,
        typer.Option(
            "--path",
            help=(
                "Path to the directory with your app's pyproject.toml "
                "(defaults to current directory)"
            ),
        ),
    ] = None,
    app_id: Annotated[
        str | None,
        typer.Option(
            "--app-id",
            help="ID of the app whose environment variable should be deleted.",
        ),
    ] = None,
    yes: Annotated[
        bool,
        typer.Option(
            "--yes",
            "-y",
            help="Confirm deletion without prompting.",
        ),
    ] = False,
    no_redeploy: Annotated[
        bool,
        typer.Option(
            "--no-redeploy",
            help="Delete the environment variable without redeploying the app.",
        ),
    ] = False,
    json_output: JsonOutputOption = False,
) -> Any:
    """
    Delete an environment variable and redeploy the app by default.

    Succeeds even if the variable is already absent.
    """

    toolkit = get_user_command_context(ctx).toolkit

    target_app_id = resolve_app_id_or_fail(
        toolkit, app_id=app_id, path=path or path_arg
    )
    name_provided = name is not None

    with APIClient() as client:
        if not name:
            if toolkit.mode == "json":
                toolkit.fail(
                    "missing_required_input",
                    "Environment variable name is required.",
                    hint="Pass NAME to choose an environment variable.",
                )

            with toolkit.progress(
                "Fetching environment variables...", transient=True
            ) as progress:
                with client.handle_http_errors(progress, toolkit=toolkit):
                    environment_variables = client.get_environment_variables(
                        app_id=target_app_id
                    )

            toolkit.print_title("environment variables")
            toolkit.print_line()

            if not environment_variables.data:
                toolkit.print("No environment variables found.", bullet=False)
                return

            name = toolkit.ask(
                "Select the environment variable to delete:",
                options=[
                    Option({"name": env_var.name, "value": env_var.name})
                    for env_var in environment_variables.data
                ],
                bullet=False,
            )

            assert name
        else:
            if not validate_environment_variable_name(name):
                toolkit.fail(
                    "invalid_input",
                    f"The environment variable name [bold]{name}[/] is invalid.",
                )

            toolkit.print_line()

        if name_provided and not yes:
            if toolkit.mode == "json":
                toolkit.fail(
                    "missing_required_input",
                    "Deletion confirmation is required.",
                    hint="Pass --yes to confirm deletion.",
                )

            should_delete = toolkit.confirm(
                f"Delete [bold]{name}[/]?",
                default=False,
                bullet=False,
            )
            if not should_delete:
                toolkit.print_title("environment variables")
                toolkit.print_line()
                toolkit.print("Deletion cancelled.", bullet=False)
                raise typer.Exit(0)
            toolkit.print_line()

        with toolkit.progress(
            "Deleting environment variable", transient=True
        ) as progress:
            with client.handle_http_errors(progress, toolkit=toolkit):
                client.batch_environment_variables(
                    app_id=target_app_id,
                    upsert={},
                    delete=[name],
                    redeploy=not no_redeploy,
                )

    toolkit.success(
        EnvironmentVariableDeleteOutput(
            app_id=target_app_id, name=name, show_tag=name_provided
        ),
        render_output=_render_environment_variable_delete_output,
    )
