"""Tests for brynq.profiles — bot profile management and skill matching."""

import json
import pytest


@pytest.fixture(autouse=True)
def _isolate_profiles(tmp_path, monkeypatch):
    """Redirect profile storage to temp directory."""
    profiles_dir = tmp_path / "profiles"
    profiles_dir.mkdir()
    channels_dir = tmp_path / "channels"
    channels_dir.mkdir()
    monkeypatch.setattr("brynq.profiles.PROFILES_DIR", profiles_dir)
    monkeypatch.setattr("brynq.profiles.RATINGS_LOG", profiles_dir / "_ratings.jsonl")
    monkeypatch.setattr("brynq.profiles.CHANNELS_DIR", channels_dir)


class TestCreateProfile:
    def test_creates_profile(self):
        from brynq.profiles import create_or_update_profile, PROFILES_DIR
        profile = create_or_update_profile(
            bio="I review code", skills=["python", "testing"],
            session_id="a1", session_name="reviewer", platform="claude",
        )
        assert profile["bio"] == "I review code"
        assert profile["skills"] == ["python", "testing"]
        assert (PROFILES_DIR / "a1.json").exists()

    def test_update_existing_profile(self):
        from brynq.profiles import create_or_update_profile
        create_or_update_profile(bio="v1", session_id="a1", session_name="bot", platform="claude")
        updated = create_or_update_profile(bio="v2", session_id="a1", session_name="bot", platform="claude")
        assert updated["bio"] == "v2"

    def test_default_availability(self):
        from brynq.profiles import create_or_update_profile
        p = create_or_update_profile(session_id="a1", session_name="b", platform="c")
        assert p["availability"] == "available"


class TestGetProfile:
    def test_get_existing(self):
        from brynq.profiles import create_or_update_profile, get_profile
        create_or_update_profile(bio="test", session_id="a1", session_name="b", platform="c")
        p = get_profile(session_id="a1")
        assert p is not None
        assert p["bio"] == "test"

    def test_get_nonexistent(self):
        from brynq.profiles import get_profile
        result = get_profile(session_id="nonexistent")
        # Returns empty dict or None for nonexistent profiles
        assert not result or result == {}


class TestListProfiles:
    def test_empty(self):
        from brynq.profiles import list_profiles
        assert list_profiles() == []

    def test_lists_created(self):
        from brynq.profiles import create_or_update_profile, list_profiles
        create_or_update_profile(session_id="a1", session_name="b1", platform="c")
        create_or_update_profile(session_id="a2", session_name="b2", platform="c")
        assert len(list_profiles()) == 2

    def test_filter_by_availability(self):
        from brynq.profiles import create_or_update_profile, list_profiles
        create_or_update_profile(availability="available", session_id="a1", session_name="b", platform="c")
        create_or_update_profile(availability="offline", session_id="a2", session_name="b", platform="c")
        avail = list_profiles(availability="available")
        assert len(avail) == 1
        assert avail[0]["session_id"] == "a1"

    def test_filter_by_skill(self):
        from brynq.profiles import create_or_update_profile, list_profiles
        create_or_update_profile(skills=["python"], session_id="a1", session_name="b", platform="c")
        create_or_update_profile(skills=["rust"], session_id="a2", session_name="b", platform="c")
        result = list_profiles(skill="python")
        assert len(result) == 1
        assert result[0]["session_id"] == "a1"


class TestAvailability:
    def test_update_availability(self):
        from brynq.profiles import create_or_update_profile, update_availability, get_profile
        create_or_update_profile(session_id="a1", session_name="b", platform="c")
        update_availability("busy", session_id="a1")
        p = get_profile(session_id="a1")
        assert p["availability"] == "busy"


class TestSkills:
    def test_add_skill(self):
        from brynq.profiles import create_or_update_profile, add_skill, get_profile
        create_or_update_profile(skills=["python"], session_id="a1", session_name="b", platform="c")
        add_skill("testing", session_id="a1")
        p = get_profile(session_id="a1")
        assert "testing" in p["skills"]

    def test_add_duplicate_skill(self):
        from brynq.profiles import create_or_update_profile, add_skill, get_profile
        create_or_update_profile(skills=["python"], session_id="a1", session_name="b", platform="c")
        add_skill("python", session_id="a1")
        p = get_profile(session_id="a1")
        assert p["skills"].count("python") == 1


class TestRating:
    def test_rate_bot(self):
        from brynq.profiles import create_or_update_profile, rate_bot, get_profile
        create_or_update_profile(session_id="a1", session_name="b", platform="c")
        result = rate_bot("a1", rating=4.5, review="Good work")
        assert "error" not in result
        p = get_profile(session_id="a1")
        assert p["reputation"] > 0


class TestFindBots:
    def test_find_by_skills(self):
        from brynq.profiles import create_or_update_profile, find_bots_for_skills
        create_or_update_profile(skills=["python", "testing"], session_id="a1", session_name="b1", platform="c")
        create_or_update_profile(skills=["rust"], session_id="a2", session_name="b2", platform="c")
        matches = find_bots_for_skills(required_skills=["python"])
        assert len(matches) >= 1
        assert any(m["session_id"] == "a1" for m in matches)

    def test_find_no_match(self):
        from brynq.profiles import create_or_update_profile, find_bots_for_skills
        create_or_update_profile(skills=["python"], session_id="a1", session_name="b", platform="c")
        matches = find_bots_for_skills(required_skills=["quantum_computing"])
        assert len(matches) == 0
