from __future__ import annotations

from dataclasses import dataclass

from k4s.core.executor import Executor
from k4s.core.executor import ExecutorError
from k4s.recipes.common.ini import get_ini_value
from k4s.recipes.common.run import q, run
from k4s.ui.ui import Ui


@dataclass(frozen=True)
class DataikuStatus:
    dss_status: str | None
    listening: bool
    port: int
    ssl_enabled: bool | None
    http_code: int | None


def check_status(ui: Ui, ex: Executor, *, os_user: str, data_dir: str, port: int) -> DataikuStatus:
    """Check Dataiku DSS status on the target host.

    Uses `bin/dss status` (most reliable across init systems) and checks whether
    the configured port is listening. Also performs a lightweight HTTP(S) check
    on localhost (best-effort).
    """
    dss_cmd = f"sudo -n -u {q(os_user)} {q(data_dir)}/bin/dss status"
    rc, out, err = run(ex, dss_cmd)
    if rc != 0:
        # If Dataiku isn't installed, the command path will fail.
        if "No such file" in (err or out):
            raise ExecutorError(f"Dataiku not found at {data_dir}.")
    dss_status = (out or err).strip() or None

    # Listening check (best-effort).
    _, out2, _ = run(ex, f"sudo -n ss -ltn 'sport = :{int(port)}' 2>/dev/null || true")
    listening = bool(out2.strip())

    # Detect SSL from install.ini (best-effort).
    ssl_enabled: bool | None = None
    try:
        ini = ex.read_remote_file_content(f"{data_dir}/install.ini", use_sudo=True)
        ssl_val = get_ini_value(ini, section="server", option="ssl")
        if ssl_val is not None:
            ssl_enabled = ssl_val.strip().lower() in {"true", "1", "yes", "y"}
    except Exception:
        ssl_enabled = None

    # HTTP(S) local probe (best-effort).
    http_code: int | None = None
    scheme = "https" if ssl_enabled else "http"
    curl_flags = "-sS --connect-timeout 3 --max-time 8"
    if scheme == "https":
        curl_flags += " -k"
    cmd = f"curl {curl_flags} -o /dev/null -w %{{http_code}} {q(f'{scheme}://127.0.0.1:{int(port)}/')}"
    rc3, out3, _ = run(ex, cmd + " || true")
    if rc3 == 0 and out3.strip().isdigit():
        code = int(out3.strip())
        if code != 0:
            http_code = code

    # Render summary.
    if dss_status:
        is_running = "RUNNING" in dss_status.upper()
        dot = "[green]●[/green]" if is_running else "[red]●[/red]"
        dss_display = f"{dot} {dss_status}"
    else:
        dss_display = "[red]●[/red] -"

    rows: list[list[str]] = []
    rows.append(["dss status", dss_display])
    rows.append(["port listening", "yes" if listening else "no"])
    rows.append(["ssl enabled", "-" if ssl_enabled is None else ("yes" if ssl_enabled else "no")])
    rows.append(["local http code", "-" if http_code is None else str(http_code)])
    ui.table(title="Dataiku runtime status", columns=["check", "result"], rows=rows)

    return DataikuStatus(
        dss_status=dss_status,
        listening=listening,
        port=port,
        ssl_enabled=ssl_enabled,
        http_code=http_code,
    )

