"""Regression tests for issue #3066: skills panel disabled-state read path
must resolve against the active WebUI profile, not the process-global
HERMES_HOME.
"""
import yaml
from pathlib import Path

from tests.conftest import requires_agent_modules


def _write_config(config_path: Path, data: dict) -> None:
    config_path.parent.mkdir(parents=True, exist_ok=True)
    config_path.write_text(yaml.dump(data), encoding="utf-8")


def _write_skill(skills_dir: Path, name: str) -> None:
    skill_dir = skills_dir / name
    skill_dir.mkdir(parents=True, exist_ok=True)
    (skill_dir / "SKILL.md").write_text(
        f"---\nname: {name}\ndescription: A test skill\n---\n\n# {name}\n",
        encoding="utf-8",
    )


def test_disabled_read_uses_active_profile_config(tmp_path, monkeypatch):
    """_get_disabled_skill_names_for_profile reads from the active profile's
    config.yaml (via _get_config_path), not from HERMES_HOME."""
    from api import routes

    profile_home = tmp_path / "profiles" / "work"
    config_path = profile_home / "config.yaml"
    _write_config(config_path, {"skills": {"disabled": ["skill-x", "skill-y"]}})

    # Point _get_config_path at the profile config
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)

    result = routes._get_disabled_skill_names_for_profile()
    assert result == {"skill-x", "skill-y"}


def test_disabled_read_prefers_platform_disabled_webui(tmp_path, monkeypatch):
    """When platform_disabled.webui exists, it takes precedence over the
    global disabled list."""
    from api import routes

    config_path = tmp_path / "config.yaml"
    _write_config(config_path, {
        "skills": {
            "disabled": ["global-disabled"],
            "platform_disabled": {
                "webui": ["webui-disabled-a", "webui-disabled-b"],
                "telegram": ["telegram-disabled"],
            },
        }
    })
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)

    result = routes._get_disabled_skill_names_for_profile()
    assert result == {"webui-disabled-a", "webui-disabled-b"}
    assert "global-disabled" not in result


def test_disabled_read_falls_back_to_global_disabled(tmp_path, monkeypatch):
    """When platform_disabled.webui is absent, falls back to skills.disabled."""
    from api import routes

    config_path = tmp_path / "config.yaml"
    _write_config(config_path, {"skills": {"disabled": ["fallback-skill"]}})
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)

    result = routes._get_disabled_skill_names_for_profile()
    assert result == {"fallback-skill"}


def test_disabled_read_empty_when_no_config(tmp_path, monkeypatch):
    """Returns empty set when config.yaml does not exist."""
    from api import routes

    config_path = tmp_path / "nonexistent" / "config.yaml"
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)

    result = routes._get_disabled_skill_names_for_profile()
    assert result == set()


def test_disabled_read_empty_when_no_skills_section(tmp_path, monkeypatch):
    """Returns empty set when config has no skills section."""
    from api import routes

    config_path = tmp_path / "config.yaml"
    _write_config(config_path, {"model": "gpt-4"})
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)

    result = routes._get_disabled_skill_names_for_profile()
    assert result == set()


@requires_agent_modules
def test_skills_list_disabled_reflects_active_profile(tmp_path, monkeypatch):
    """_skills_list_from_dir marks skills as disabled based on the active
    profile's config, not the process-global HERMES_HOME."""
    from api import routes

    # Set up skills directory with two skills
    skills_dir = tmp_path / "skills"
    _write_skill(skills_dir, "skill-a")
    _write_skill(skills_dir, "skill-b")

    # Profile config disables only skill-a
    config_path = tmp_path / "config.yaml"
    _write_config(config_path, {"skills": {"disabled": ["skill-a"]}})
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)
    monkeypatch.setattr("api.routes._active_skills_dir", lambda: skills_dir)

    result = routes._skills_list_from_dir(skills_dir)
    skills = {s["name"]: s for s in result["skills"]}

    assert skills["skill-a"]["disabled"] is True
    assert skills["skill-b"]["disabled"] is False


@requires_agent_modules
def test_profile_switch_changes_disabled_state(tmp_path, monkeypatch):
    """Simulates switching profiles: disabled state should follow the active
    profile's config, not remain stuck on the original profile."""
    from api import routes

    # Two profile configs with different disabled lists
    profile_a_config = tmp_path / "profile-a" / "config.yaml"
    profile_b_config = tmp_path / "profile-b" / "config.yaml"
    _write_config(profile_a_config, {"skills": {"disabled": ["skill-x"]}})
    _write_config(profile_b_config, {"skills": {"disabled": ["skill-y"]}})

    # Skills dir with both skills
    skills_dir = tmp_path / "skills"
    _write_skill(skills_dir, "skill-x")
    _write_skill(skills_dir, "skill-y")
    monkeypatch.setattr("api.routes._active_skills_dir", lambda: skills_dir)

    # "Active" profile A
    monkeypatch.setattr("api.routes._get_config_path", lambda: profile_a_config)
    result_a = routes._skills_list_from_dir(skills_dir)
    skills_a = {s["name"]: s for s in result_a["skills"]}
    assert skills_a["skill-x"]["disabled"] is True
    assert skills_a["skill-y"]["disabled"] is False

    # "Switch" to profile B
    monkeypatch.setattr("api.routes._get_config_path", lambda: profile_b_config)
    result_b = routes._skills_list_from_dir(skills_dir)
    skills_b = {s["name"]: s for s in result_b["skills"]}
    assert skills_b["skill-x"]["disabled"] is False
    assert skills_b["skill-y"]["disabled"] is True


def test_normalize_disabled_set_handles_edge_cases():
    """_normalize_disabled_set handles None, str, list, and whitespace."""
    from api.routes import _normalize_disabled_set

    assert _normalize_disabled_set(None) == set()
    assert _normalize_disabled_set("single") == {"single"}
    assert _normalize_disabled_set(["a", "b"]) == {"a", "b"}
    assert _normalize_disabled_set([" spaced ", "  "]) == {"spaced"}
    assert _normalize_disabled_set([]) == set()


def test_disabled_read_decodes_json_array_string(tmp_path, monkeypatch):
    """Issue #7120: skills.disabled stored as a JSON-array string (the shape
    produced by `hermes config set skills.disabled ...`) must decode to the
    real names, not one literal entry."""
    from api import routes

    config_path = tmp_path / "config.yaml"
    _write_config(config_path, {"skills": {"disabled": '["skill-x", "skill-y"]'}})
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)

    result = routes._get_disabled_skill_names_for_profile()
    assert result == {"skill-x", "skill-y"}


def test_disabled_read_platform_webui_decodes_json_array_string(tmp_path, monkeypatch):
    """Issue #7120: platform_disabled.webui stored as a JSON-array string is
    decoded the same way as the global disabled list."""
    from api import routes

    config_path = tmp_path / "config.yaml"
    _write_config(config_path, {
        "skills": {
            "disabled": ["global-disabled"],
            "platform_disabled": {"webui": '["webui-disabled-a", "webui-disabled-b"]'},
        }
    })
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)

    result = routes._get_disabled_skill_names_for_profile()
    assert result == {"webui-disabled-a", "webui-disabled-b"}
    assert "global-disabled" not in result


@requires_agent_modules
def test_skills_list_disabled_decodes_json_array_string(tmp_path, monkeypatch):
    """Issue #7120: the Skills panel (skills list endpoint) must report both
    skills as disabled when config.yaml stores disabled as a JSON-array string."""
    from api import routes

    skills_dir = tmp_path / "skills"
    _write_skill(skills_dir, "skill-a")
    _write_skill(skills_dir, "skill-b")

    config_path = tmp_path / "config.yaml"
    _write_config(config_path, {"skills": {"disabled": '["skill-a", "skill-b"]'}})
    monkeypatch.setattr("api.routes._get_config_path", lambda: config_path)
    monkeypatch.setattr("api.routes._active_skills_dir", lambda: skills_dir)

    result = routes._skills_list_from_dir(skills_dir)
    skills = {s["name"]: s for s in result["skills"]}

    assert skills["skill-a"]["disabled"] is True
    assert skills["skill-b"]["disabled"] is True
