from __future__ import annotations

import sys
import types
from pathlib import Path
from types import SimpleNamespace


REPO_ROOT = Path(__file__).resolve().parents[1]


def _profile_row(name: str, path: Path, *, is_default: bool = False):
    return SimpleNamespace(
        name=name,
        path=path,
        is_default=is_default,
        gateway_running=False,
        model=None,
        provider=None,
        has_env=False,
    )


def _install_fake_hermes_profiles(monkeypatch, rows):
    hermes_cli = types.ModuleType("hermes_cli")
    profiles_mod = types.ModuleType("hermes_cli.profiles")
    profiles_mod.list_profiles = lambda: rows
    monkeypatch.setitem(sys.modules, "hermes_cli", hermes_cli)
    monkeypatch.setitem(sys.modules, "hermes_cli.profiles", profiles_mod)


def test_profile_yaml_visible_false_is_exposed_as_hidden(monkeypatch, tmp_path):
    import api.profiles as profiles

    hidden = tmp_path / "profiles" / "worker-coder"
    visible = tmp_path / "profiles" / "human"
    missing = tmp_path / "profiles" / "missing-meta"
    malformed = tmp_path / "profiles" / "malformed"
    string_false = tmp_path / "profiles" / "string-false"
    for path in (hidden, visible, missing, malformed, string_false):
        path.mkdir(parents=True)
    (hidden / "profile.yaml").write_text("visible: false\n", encoding="utf-8")
    (visible / "profile.yaml").write_text("visible: true\n", encoding="utf-8")
    (malformed / "profile.yaml").write_text("visible: [\n", encoding="utf-8")
    (string_false / "profile.yaml").write_text('visible: "false"\n', encoding="utf-8")

    rows = [
        _profile_row("worker-coder", hidden),
        _profile_row("human", visible),
        _profile_row("missing-meta", missing),
        _profile_row("malformed", malformed),
        _profile_row("string-false", string_false),
    ]
    _install_fake_hermes_profiles(monkeypatch, rows)
    monkeypatch.setattr(profiles, "_get_profile_skills_stats", lambda _path: (0, 0))
    monkeypatch.setattr(profiles, "get_active_profile_name", lambda: "human")

    result = {row["name"]: row["visible"] for row in profiles.list_profiles_api()}

    assert result == {
        "worker-coder": False,
        "human": True,
        "missing-meta": True,
        "malformed": True,
        "string-false": True,
    }


def test_default_profile_fallback_stays_visible(monkeypatch):
    import api.profiles as profiles

    monkeypatch.setattr(profiles, "_get_profile_skills_stats", lambda _path: (0, 0))

    assert profiles._default_profile_dict()["visible"] is True


def _panels_js() -> str:
    return (REPO_ROOT / "static" / "panels.js").read_text(encoding="utf-8")


def _function_body(src: str, signature: str) -> str:
    start = src.find(signature)
    assert start != -1, f"{signature} not found"
    i = src.find("{", start)
    depth = 0
    for j in range(i, len(src)):
        if src[j] == "{":
            depth += 1
        elif src[j] == "}":
            depth -= 1
            if depth == 0:
                return src[start : j + 1]
    raise AssertionError(f"could not find end of {signature}")


def test_profile_dropdown_filters_hidden_profiles_but_preserves_active():
    body = _function_body(_panels_js(), "function renderProfileDropdown(data)")

    assert "const allProfiles = data.profiles || [];" in body
    assert "allProfiles.some(p => p.name === S.activeProfile)" in body
    assert "const profiles = allProfiles.filter(p => p && (p.visible !== false || p.name === active));" in body


def test_profiles_management_panel_still_renders_all_profiles():
    body = _function_body(_panels_js(), "async function loadProfilesPanel()")

    assert "for (const p of data.profiles)" in body
    assert "visible !== false" not in body
