"""Small terminal styling helpers for consistent CLI UX."""

from __future__ import annotations

import os
import re
import shutil
import sys
import textwrap

_COLOR_ENABLED = False

_RESET = "\x1b[0m"
_BOLD = "\x1b[1m"
_DIM = "\x1b[2m"
_FG_RED = "\x1b[31m"
_FG_GREEN = "\x1b[32m"
_FG_YELLOW = "\x1b[33m"
_FG_BLUE = "\x1b[34m"
_FG_MAGENTA = "\x1b[35m"
_FG_CYAN = "\x1b[36m"
_FG_WHITE = "\x1b[37m"
_ANSI_RE = re.compile(r"\x1b\[[0-9;]*m")


def _normalize_mode(value):
    text = str(value or "").strip().lower()
    if text in {"always", "auto", "never"}:
        return text
    return ""


def _stream_supports_color(stream):
    try:
        return bool(stream) and bool(stream.isatty())
    except Exception:
        return False


def _enable_windows_vt_processing(stream):
    if os.name != "nt":
        return True
    target = stream if stream is not None else sys.stdout
    if target not in {sys.stdout, sys.stderr}:
        return False
    try:
        import ctypes

        kernel32 = ctypes.windll.kernel32
        std_handle_id = -11 if target is sys.stdout else -12
        handle = kernel32.GetStdHandle(std_handle_id)
        if handle in (0, -1):
            return False
        mode = ctypes.c_uint()
        if kernel32.GetConsoleMode(handle, ctypes.byref(mode)) == 0:
            return False
        enable_vt = 0x0004
        if mode.value & enable_vt:
            return True
        updated_mode = ctypes.c_uint(mode.value | enable_vt)
        if kernel32.SetConsoleMode(handle, updated_mode) == 0:
            return False
        return True
    except Exception:
        return False


def configure(*, color_mode="", stream=None):
    global _COLOR_ENABLED
    mode = _normalize_mode(color_mode)
    if not mode:
        env_mode = _normalize_mode(os.environ.get("HIVE_TRACE_COLOR"))
        mode = env_mode or "auto"
    if str(os.environ.get("NO_COLOR") or "").strip():
        _COLOR_ENABLED = False
        return
    if mode == "always":
        _COLOR_ENABLED = _enable_windows_vt_processing(stream or sys.stdout)
        return
    if mode == "never":
        _COLOR_ENABLED = False
        return
    _COLOR_ENABLED = _stream_supports_color(stream or sys.stdout) and _enable_windows_vt_processing(stream or sys.stdout)


def enabled():
    return bool(_COLOR_ENABLED)


def style(text, *, color="", bold=False, dim=False):
    value = str(text or "")
    if not _COLOR_ENABLED:
        return value
    codes = []
    if bold:
        codes.append(_BOLD)
    if dim:
        codes.append(_DIM)
    if color:
        codes.append(str(color))
    if not codes:
        return value
    return f"{''.join(codes)}{value}{_RESET}"


def visible_len(text):
    value = str(text or "")
    return len(_ANSI_RE.sub("", value))


def pad(text, width, *, align="left"):
    value = str(text or "")
    target = max(0, int(width or 0))
    length = visible_len(value)
    if length >= target:
        return value
    spaces = " " * (target - length)
    if str(align).strip().lower() == "right":
        return f"{spaces}{value}"
    return f"{value}{spaces}"


def terminal_width(default=100):
    try:
        width = int(shutil.get_terminal_size(fallback=(default, 24)).columns)
        return max(60, width)
    except Exception:
        return int(default)


def wrap_text(text, *, width=None, initial_indent="", subsequent_indent=""):
    value = str(text or "")
    target = max(40, int(width or terminal_width()))
    clean = _ANSI_RE.sub("", value)
    lines = textwrap.wrap(
        clean,
        width=target,
        initial_indent=initial_indent,
        subsequent_indent=subsequent_indent,
        break_long_words=False,
        break_on_hyphens=False,
    )
    return lines or [f"{initial_indent}{clean}"]


def wrap_kv(key, value, *, width=None, indent="  "):
    label = str(key or "").strip() or "value"
    prefix = f"{indent}{label}="
    return wrap_text(
        str(value or ""),
        width=width,
        initial_indent=prefix,
        subsequent_indent=" " * len(prefix),
    )


def section(text):
    label = str(text or "").strip() or "section"
    core = f" {label} "
    width = 72
    fill = max(8, width - len(core))
    left = fill // 2
    right = fill - left
    return style(f"\n{'-' * left}{core}{'-' * right}", color=_FG_CYAN, bold=True)


def section_inline(text):
    label = str(text or "").strip() or "section"
    core = f" {label} "
    width = 72
    fill = max(8, width - len(core))
    left = fill // 2
    right = fill - left
    return style(f"{'-' * left}{core}{'-' * right}", color=_FG_CYAN, bold=True)


def key(text):
    return style(text, bold=True)


def help_key(text):
    return style(text, color=_FG_CYAN, bold=True)


def muted(text):
    return style(text, dim=True)


def brand(text):
    return style(text, color=_FG_WHITE, bold=True)


def info(text):
    return style(text, color=_FG_BLUE)


def hint(text):
    return style(text, color=_FG_CYAN)


def ok(text):
    return style(text, color=_FG_GREEN, bold=True)


def warn(text):
    return style(text, color=_FG_YELLOW, bold=True)


def err(text):
    return style(text, color=_FG_RED, bold=True)


def status_text(status):
    value = str(status or "unknown")
    norm = value.strip().lower()
    if norm in {"success", "ok", "active"}:
        return ok(value)
    if norm in {"failed", "error"}:
        return err(value)
    if norm in {"running", "idle", "running_active"}:
        return warn(value)
    if norm in {"archived"}:
        return style(value, color=_FG_MAGENTA, bold=True)
    if norm in {"unknown", "running_unknown"}:
        return style(value, color=_FG_YELLOW)
    return style(value, color=_FG_BLUE)


def rank_text(rank):
    value = str(rank or "")
    norm = value.strip().lower()
    if norm == "stable_anchor":
        return ok(value)
    if norm == "semi_stable_anchor":
        return warn(value)
    if norm == "weak_anchor":
        return err(value)
    return value


def style_help_text(text):
    raw = str(text or "")
    if not enabled():
        return raw
    lines = raw.splitlines()
    out = []
    continuation_col = None
    continuation_desc_offset = 2
    for line in lines:
        stripped = line.strip()
        lower = stripped.lower()
        if lower.startswith("usage:"):
            idx = line.lower().find("usage:")
            if idx >= 0:
                label = style("USAGE:", color=_FG_CYAN, bold=True)
                rest = line[idx + len("usage:") :]
                out.append(f"{line[:idx]}{label}{rest}")
                continuation_col = None
                continuation_desc_offset = 2
                continue
        if lower.startswith("* denotes"):
            out.append(style(line, color=_FG_CYAN, bold=True))
            continuation_col = None
            continuation_desc_offset = 2
            continue
        if stripped.endswith(":") and (not line.startswith("  ")):
            title = stripped[:-1].strip() or "section"
            if out and str(out[-1]).strip():
                out.append("")
            out.append(section_inline(title.upper()))
            continuation_col = None
            continuation_desc_offset = 2
            continue
        match = re.match(r"^(\s*)(\S(?:.*?\S)?)(\s{2,})(.*)$", line)
        if match:
            indent, left, sep, right = match.groups()
            marker = " "
            desc = right
            if str(right).startswith("* "):
                marker = "*"
                desc = str(right)[2:].lstrip()
            marker_text = style(marker, color=_FG_CYAN, bold=True) if marker.strip() else " "
            out.append(f"{indent}{help_key(left)}{sep}{marker_text} {desc}")
            continuation_col = len(indent) + len(left) + len(sep)
            continue
        if continuation_col is not None:
            base_prefix = " " * int(max(0, continuation_col))
            if line.startswith(base_prefix) and stripped:
                desc_text = line[continuation_col:]
                out.append(f"{base_prefix}{' ' * continuation_desc_offset}{desc_text.lstrip()}")
                continue
            if not stripped:
                continuation_col = None
                continuation_desc_offset = 2
        out.append(line)
    return "\n".join(out) + ("\n" if raw.endswith("\n") or out else "")
