"""CLI commands for managing TLS certificates on products."""
import click

from k4s.cli.state import CliState
from k4s.cli.target import resolve_target
from k4s.cli.errors import exit_with_error
from k4s.cli.verbosity import apply_command_ui_overrides
from k4s.core.products import run_steps
from k4s.core.executor import Executor
from k4s.recipes.dataiku.tls import DataikuTlsPlan
from k4s.recipes.dataiku.tls import build_tls_steps as build_dataiku_tls_steps
from k4s.recipes.nexus.tls import NexusTlsPlan
from k4s.recipes.nexus.tls import build_tls_steps as build_nexus_tls_steps


@click.group()
@click.pass_context
def tls(ctx):
    """Manage TLS for products."""
    pass


@tls.group("enable")
@click.pass_context
def enable(ctx):
    """Enable TLS on a product installation.

    \b
    Products:
      dataiku   Enable TLS on Dataiku DSS (native HTTPS)
      nexus     Enable TLS on Nexus via nginx reverse proxy
    """
    pass


@enable.command("dataiku")
@click.option("--context", "context_name", default=None, help="Context name (or 'local'). Uses current context if omitted.")
@click.option("--os-user", default="dataiku", show_default=True, help="OS user that owns the installation.")
@click.option("--os-group", default="dataiku", show_default=True, help="OS group that owns the installation.")
@click.option("--data-dir", default="/data/dataiku/DATA_DIR", show_default=True, help="Product data directory.")
@click.option("--issuer", required=True, help="Certificate issuer (self-signed|ca|acme).")
@click.option("--domain", help="Domain/CN for self-signed or ACME issuer.")
@click.option("--email", help="ACME email for registration/renewal notifications.")
@click.option("--stop-nginx/--no-stop-nginx", default=False, show_default=True, help="Temporarily stop nginx to free port 80 for ACME standalone.")
@click.option("--cert-key-path", type=click.Path(exists=True, dir_okay=False), help="Local path to TLS private key (CA issuer).")
@click.option("--cert-pem-path", type=click.Path(exists=True, dir_okay=False), help="Local path to TLS certificate PEM (CA issuer).")
@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 enable_dataiku(ctx, context_name, os_user, os_group, data_dir, issuer, domain,
                   email, stop_nginx, cert_key_path, cert_pem_path, dry_run, quiet, verbose):
    """Enable TLS on Dataiku DSS (native HTTPS).

    \b
    Examples:
      k4s tls enable dataiku --issuer self-signed --domain dss.example.com
      k4s tls enable dataiku --context prod --issuer acme --domain dss.example.com --email admin@example.com
      k4s tls enable dataiku --issuer ca --cert-key-path key.pem --cert-pem-path cert.pem
    """
    state: CliState = ctx.obj["state"]
    apply_command_ui_overrides(ctx, state, quiet=quiet, verbose=verbose)
    ui = state.ui

    try:
        c = resolve_target(state, context_name)

        plan = DataikuTlsPlan(
            os_user=os_user,
            os_group=os_group,
            data_dir=data_dir,
            issuer=issuer,
            domain=domain,
            email=email,
            stop_nginx=stop_nginx,
            cert_key_path=cert_key_path,
            cert_pem_path=cert_pem_path,
        )

        ex = Executor(c.to_server_config())
        if dry_run:
            steps = build_dataiku_tls_steps(ui, ex, plan)
            run_steps(ui, steps, dry_run=True)
        else:
            with ex:
                steps = build_dataiku_tls_steps(ui, ex, plan)
                run_steps(ui, steps, dry_run=False)

            state.history.append(
                action="tls-enable",
                product="dataiku",
                context=c.name,
                host=c.host,
                params={"issuer": issuer, "domain": domain},
            )
            ui.success("TLS enabled for Dataiku DSS.")
    except Exception as e:
        exit_with_error(ctx, ui, e, code=1)


@enable.command("nexus")
@click.option("--context", "context_name", default=None, help="Context name (or 'local'). Uses current context if omitted.")
@click.option("--http-port", default=8081, show_default=True, type=int, help="Nexus HTTP port.")
@click.option("--https-port", default=443, show_default=True, type=int, help="HTTPS listen port for nginx.")
@click.option("--issuer", required=True, help="Certificate issuer (self-signed|ca|acme).")
@click.option("--domain", required=True, help="Domain name for the Nexus web UI.")
@click.option("--email", help="ACME email for registration/renewal notifications.")
@click.option("--cert-key-path", type=click.Path(exists=True, dir_okay=False), help="Local path to TLS private key (CA issuer).")
@click.option("--cert-pem-path", type=click.Path(exists=True, dir_okay=False), help="Local path to TLS certificate PEM (CA issuer).")
@click.option("--docker-port", default=None, type=int, help="HTTPS listen port for Docker registry proxy (enables Docker TLS).")
@click.option("--docker-domain", default=None, help="Domain for Docker registry (required with --docker-port).")
@click.option(
    "--docker-connector-port",
    default=8081,
    show_default=True,
    type=int,
    help="Docker upstream HTTP port. For path-based routing this is typically the Nexus HTTP port (8081). For legacy port connectors, set this to the repo connector port.",
)
@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 enable_nexus(ctx, context_name, http_port, https_port, issuer, domain, email,
                 cert_key_path, cert_pem_path, docker_port, docker_domain,
                 docker_connector_port, dry_run, quiet, verbose):
    """Enable TLS on Nexus via nginx reverse proxy.

    \b
    Examples:
      k4s tls enable nexus --issuer self-signed --domain nexus.example.com
      k4s tls enable nexus --issuer acme --domain nexus.example.com --email admin@example.com
      k4s tls enable nexus --issuer ca --domain nexus.example.com --cert-key-path key.pem --cert-pem-path cert.pem
      k4s tls enable nexus --issuer acme --domain nexus.example.com --email a@b.com --docker-port 8443 --docker-domain registry.example.com
    """
    state: CliState = ctx.obj["state"]
    apply_command_ui_overrides(ctx, state, quiet=quiet, verbose=verbose)
    ui = state.ui

    try:
        c = resolve_target(state, context_name)

        plan = NexusTlsPlan(
            http_port=http_port,
            https_port=https_port,
            issuer=issuer,
            domain=domain,
            email=email,
            cert_key_path=cert_key_path,
            cert_pem_path=cert_pem_path,
            docker_port=docker_port,
            docker_domain=docker_domain,
            docker_connector_port=docker_connector_port,
        )

        ex = Executor(c.to_server_config())
        if dry_run:
            steps = build_nexus_tls_steps(ui, ex, plan)
            run_steps(ui, steps, dry_run=True)
        else:
            with ex:
                steps = build_nexus_tls_steps(ui, ex, plan)
                run_steps(ui, steps, dry_run=False)

            params = {"issuer": issuer, "domain": domain}
            if docker_port:
                params["docker_port"] = docker_port
                params["docker_domain"] = docker_domain

            state.history.append(
                action="tls-enable",
                product="nexus",
                context=c.name,
                host=c.host,
                params=params,
            )
            ui.success("TLS enabled for Nexus.")
    except Exception as e:
        exit_with_error(ctx, ui, e, code=1)
