"""CLI commands for pushing artifacts to registries."""
from __future__ import annotations

import click

from k4s.cli.errors import exit_with_error
from k4s.cli.state import CliState
from k4s.cli.target import resolve_target
from k4s.cli.verbosity import apply_command_ui_overrides
from k4s.core.executor import Executor
from k4s.core.products import Step, run_steps
from k4s.recipes.common.run import check, q, run


@click.group()
def push():
    """Push artifacts to registries."""
    pass


@push.command("image")
@click.argument("tag")
@click.option("--context", "context_name", default=None, help="Context name (or 'local'). Uses current context if omitted.")
@click.option("--registry", required=True, help="Target Docker registry URL.")
@click.option("--registry-username", default=None, help="Registry username.")
@click.option("--registry-password", default=None, help="Registry password (prefer --ask-registry-password).")
@click.option("--ask-registry-password", is_flag=True, help="Prompt for registry password.")
@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 image(
    ctx,
    tag,
    context_name,
    registry,
    registry_username,
    registry_password,
    ask_registry_password,
    dry_run,
    quiet,
    verbose,
):
    """Push a Docker image to a registry.

    TAG is the local image name/tag to push (e.g. dss-base-image or dss-base-image:v1).

    \b
    Examples:
      k4s push image dss-base-image --registry nexus.example.com:8080
      k4s push image dss-base-image:v1 --registry nexus.example.com:8080 \\
            --registry-username admin --ask-registry-password
    """
    state: CliState = ctx.obj["state"]
    apply_command_ui_overrides(ctx, state, quiet=quiet, verbose=verbose)
    ui = state.ui

    try:
        if registry_password and ask_registry_password:
            raise ValueError("Use either --registry-password or --ask-registry-password, not both.")

        if ask_registry_password:
            registry_password = click.prompt(
                "Registry password",
                hide_input=True,
                confirmation_prompt=False,
            )

        c = resolve_target(state, context_name)
        ex = Executor(c.to_server_config())

        remote_tag = f"{registry.rstrip('/')}/{tag}"

        def _preflight():
            ui.log(f"Checking image exists: {tag}")
            rc, _, _ = run(ex, f"docker image inspect {q(tag)}", silent=True)
            if rc != 0:
                raise Exception(
                    f"Image '{tag}' not found on {ex.host}.\n"
                    f"Build it first with: k4s build dataiku-base-image --tag {tag}"
                )

        def _login():
            ui.log(f"Logging in to registry: {registry}")
            login_cmd = f"docker login {q(registry)}"
            if registry_username:
                login_cmd += f" --username {q(registry_username)}"
            if registry_password:
                login_cmd += " --password-stdin"
                check(ex, login_cmd, stdin_data=registry_password + "\n", silent=True)
            else:
                check(ex, login_cmd)

        def _tag():
            ui.log(f"Tagging {tag} → {remote_tag}")
            check(ex, f"docker tag {q(tag)} {q(remote_tag)}")

        def _push():
            ui.log(f"Pushing {remote_tag}")
            check(ex, f"docker push {q(remote_tag)}")

        steps: list[Step] = [
            Step(title=f"Preflight on {ex.host}", run=_preflight),
        ]
        if registry_username or registry_password:
            steps.append(Step(title=f"Docker login to {registry}", run=_login))
        steps.append(Step(title=f"Tag image as {remote_tag}", run=_tag))
        steps.append(Step(title=f"Push {remote_tag}", run=_push))

        if dry_run:
            run_steps(ui, steps, dry_run=True)
        else:
            with ex:
                run_steps(ui, steps, dry_run=False)
            state.history.append(
                action="push",
                product="image",
                context=c.name,
                host=c.host,
                params={"tag": tag, "registry": registry, "remote_tag": remote_tag},
            )
            ui.success(f"Image pushed successfully: {remote_tag}")

    except Exception as e:
        exit_with_error(ctx, ui, e, code=1)
