from __future__ import annotations

import logging

import click

from k4s.core.executor import set_executor_debug_hook
from k4s.cli.state import CliState
from k4s.ui.ui import Ui, UiOptions, Verbosity


def _verbosity_to_verbose_count(v: Verbosity) -> int:
    if v == Verbosity.quiet:
        return 0
    if v == Verbosity.normal:
        return 0
    if v == Verbosity.logs:
        return 1
    return 2  # debug


def build_ui(*, quiet: bool, verbose: int) -> Ui:
    if quiet:
        verbosity = Verbosity.quiet
    else:
        verbosity = {0: Verbosity.normal, 1: Verbosity.logs}.get(verbose, Verbosity.debug)
    return Ui(UiOptions(verbosity=verbosity))


def configure_logging() -> None:
    """Keep Python logging quiet by default."""
    logging.getLogger().setLevel(logging.WARNING)
    logging.getLogger("paramiko").setLevel(logging.WARNING)


def apply_command_ui_overrides(
    ctx: click.Context,
    state: CliState,
    *,
    quiet: bool,
    verbose: int,
) -> None:
    """Allow `-v/-q` flags at subcommand level."""
    base_quiet = state.ui.options.verbosity == Verbosity.quiet
    base_verbose = _verbosity_to_verbose_count(state.ui.options.verbosity)

    eff_quiet = base_quiet
    eff_verbose = base_verbose

    if ctx.get_parameter_source("quiet") == click.core.ParameterSource.COMMANDLINE:
        eff_quiet = bool(quiet)
    if ctx.get_parameter_source("verbose") == click.core.ParameterSource.COMMANDLINE:
        eff_verbose = int(verbose)

    if eff_quiet == base_quiet and eff_verbose == base_verbose:
        apply_runtime_verbosity_hooks(state.ui)
        return

    state.ui = build_ui(quiet=eff_quiet, verbose=eff_verbose)
    apply_runtime_verbosity_hooks(state.ui)


def apply_runtime_verbosity_hooks(ui: Ui) -> None:
    """Wire the Executor debug hook from current verbosity.

    At ``-vv`` (debug), every ``Executor.execute()`` call emits the
    command, return code, and stdout/stderr through ``Ui.debug``.
    """
    if ui.options.verbosity >= Verbosity.debug:
        set_executor_debug_hook(ui.debug)
    else:
        set_executor_debug_hook(None)
