"""CLI commands for deleting resources (verb-first: k4s delete <resource>)."""
import click

from k4s.cli.state import CliState
from k4s.cli.verbosity import apply_command_ui_overrides
from k4s.core.cluster import ClusterError, build_nodes_from_contexts
from k4s.core.executor import Executor


class OrderedDeleteGroup(click.Group):
    _order = ["cluster"]

    def list_commands(self, ctx):
        return self._order


@click.group(cls=OrderedDeleteGroup)
def delete():
    """Delete clusters and other resources."""
    pass


@delete.command("cluster")
@click.option("--control-plane", "control_planes", multiple=True, required=True, help="Context name for a control-plane node.")
@click.option("--worker", "workers", multiple=True, help="Context name for a worker node.")
@click.option("--yes", is_flag=True, help="Skip confirmation prompt.")
@click.option("--dry-run", is_flag=True, help="Print the plan without applying changes.")
@click.option("-q", "--quiet", is_flag=True, help="Only print final results and errors.")
@click.option("-v", "--verbose", count=True, help="Increase verbosity (-v logs, -vv debug).")
@click.pass_context
def cluster(ctx, control_planes, workers, yes, dry_run, quiet, verbose):
    """Uninstall RKE2 from all specified cluster nodes.

    Runs the RKE2 uninstall scripts on each node in the correct order:
    workers first, then control-plane nodes.

    \b
    Examples:
      k4s delete cluster --control-plane cp1
      k4s delete cluster --control-plane cp1 --worker w1 --worker w2
      k4s delete cluster --control-plane cp1 --yes
    """
    state: CliState = ctx.obj["state"]
    apply_command_ui_overrides(ctx, state, quiet=quiet, verbose=verbose)
    ui = state.ui

    try:
        nodes = build_nodes_from_contexts(
            state.contexts, control_planes=list(control_planes), workers=list(workers)
        )
    except (KeyError, ClusterError) as e:
        ui.error(str(e))
        ctx.exit(2)

    if dry_run:
        ui.info("Planned steps:")
        for n in nodes:
            script = "rke2-agent-uninstall.sh" if n.role == "worker" else "rke2-uninstall.sh"
            ui.info(f"  - Run {script} on {n.context.name} ({n.context.host})")
        return

    total = len(nodes)
    if not yes:
        ans = click.prompt(
            f"Uninstall RKE2 from {total} node(s)? [Y/n]",
            type=click.Choice(["Y", "n"], case_sensitive=True),
            show_choices=False,
        )
        if ans != "Y":
            ui.info("Cancelled.")
            return

    failures = []

    def _run_uninstall(n) -> None:
        sudo = (n.context.username or "").lower() not in {"root"}
        with Executor(n.context.to_server_config()) as ex:
            # Per RKE2 docs, the uninstall script lives in:
            # - /usr/local/bin/rke2-uninstall.sh (tarball install)
            # - /usr/bin/rke2-uninstall.sh       (RPM install)
            candidates = [
                "/usr/local/bin/rke2-uninstall.sh",
                "/usr/bin/rke2-uninstall.sh",
            ]

            chosen = None
            for p in candidates:
                rc, _, _ = ex.execute(f"test -x {p}", use_sudo=False)
                if rc == 0:
                    chosen = p
                    break

            if not chosen:
                # If RKE2 is already gone (no config/data dirs), treat as success.
                rc1, _, _ = ex.execute("test -d /etc/rancher/rke2", use_sudo=sudo)
                rc2, _, _ = ex.execute("test -d /var/lib/rancher/rke2", use_sudo=sudo)
                if rc1 != 0 and rc2 != 0:
                    ui.warning(f"RKE2 not found on {n.context.name}; skipping.")
                    return

                joined = ", ".join(candidates)
                raise RuntimeError(
                    "RKE2 uninstall script not found on "
                    f"{n.context.name}: {joined}\n"
                    "RKE2 appears to be installed (data directories exist). "
                    "Uninstall it manually (see docs) or reinstall then uninstall."
                )

            rc, _, err = ex.execute(chosen, use_sudo=sudo)
            if rc != 0:
                msg = err or f"Script {chosen} exited with rc={rc}"
                # If the error is about missing a password, give actionable fix instructions.
                # Note: sudo can also emit confusing messages for other failures, so only
                # treat explicit password-related errors as sudo configuration problems.
                if "a password is required" in msg.lower():
                    user = n.context.username or "<user>"
                    msg += (
                        f"\n  k4s requires passwordless sudo for infrastructure operations.\n"
                        f"  Fix A — configure NOPASSWD on the node:\n"
                        f"    echo '{user} ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/{user}\n"
                        f"  Fix B — re-add the context with username=root:\n"
                        f"    k4s context add {n.context.name} --host {n.context.host} --username root -i <key>"
                    )
                raise RuntimeError(msg)

    for n in [x for x in nodes if x.role == "worker"]:
        with ui.step(f"Uninstalling rke2-agent on {n.context.name}"):
            try:
                _run_uninstall(n)
            except Exception as e:
                failures.append(f"{n.context.name}: {e}")

    for n in [x for x in nodes if x.role == "control-plane"]:
        with ui.step(f"Uninstalling rke2-server on {n.context.name}"):
            try:
                _run_uninstall(n)
            except Exception as e:
                failures.append(f"{n.context.name}: {e}")

    if failures:
        ui.error("Some nodes failed to uninstall:")
        for f in failures:
            ui.error("")
            ui.error(f"  - {f}")
        ctx.exit(1)
    else:
        state.history.append(
            action="cluster-delete",
            product="cluster",
            params={
                "control_planes": list(control_planes),
                "workers": list(workers),
            },
        )
        ui.success("Cluster uninstalled successfully.")
