import asyncio
from pathlib import Path

import pytest

from gateway.config import GatewayConfig, Platform
from gateway.run import GatewayRunner, _profile_runtime_scope
from gateway.session import SessionSource
from hermes_constants import get_hermes_home
from hermes_cli.profiles import create_profile, get_profile_dir
from tools.memory_tool import MemoryStore, get_memory_dir


def _source(*, profile: str, platform: Platform = Platform.TELEGRAM, user_id: str = "u-1") -> SessionSource:
    return SessionSource(
        platform=platform,
        chat_id=user_id,
        user_id=user_id,
        user_name="Tester",
        chat_type="dm",
        profile=profile,
    )


def _write_memory(profile_home: Path, *, memory: str, user: str) -> None:
    mem_dir = profile_home / "memories"
    mem_dir.mkdir(parents=True, exist_ok=True)
    (mem_dir / "MEMORY.md").write_text(memory, encoding="utf-8")
    (mem_dir / "USER.md").write_text(user, encoding="utf-8")


def test_profile_runtime_scope_reads_profile_specific_memory(monkeypatch, tmp_path):
    monkeypatch.setenv("HERMES_HOME", str(tmp_path))
    create_profile("principal_alpha001", no_alias=True)
    create_profile("principal_beta0002", no_alias=True)

    alpha_home = get_profile_dir("principal_alpha001")
    beta_home = get_profile_dir("principal_beta0002")
    _write_memory(alpha_home, memory="alpha-memory", user="alpha-user")
    _write_memory(beta_home, memory="beta-memory", user="beta-user")

    with _profile_runtime_scope(alpha_home):
        alpha_store = MemoryStore()
        alpha_store.load_from_disk()
        assert get_hermes_home() == alpha_home
        assert get_memory_dir() == alpha_home / "memories"
        assert alpha_store.memory_entries == ["alpha-memory"]
        assert alpha_store.user_entries == ["alpha-user"]

    with _profile_runtime_scope(beta_home):
        beta_store = MemoryStore()
        beta_store.load_from_disk()
        assert get_hermes_home() == beta_home
        assert get_memory_dir() == beta_home / "memories"
        assert beta_store.memory_entries == ["beta-memory"]
        assert beta_store.user_entries == ["beta-user"]


@pytest.mark.asyncio
async def test_run_agent_scopes_runtime_to_source_profile(monkeypatch, tmp_path):
    monkeypatch.setenv("HERMES_HOME", str(tmp_path))
    create_profile("principal_shared01", no_alias=True)
    profile_home = get_profile_dir("principal_shared01")
    _write_memory(profile_home, memory="shared-memory", user="shared-user")

    runner = GatewayRunner.__new__(GatewayRunner)
    runner.config = GatewayConfig(multiplex_profiles=True)

    seen = {}

    async def _fake_run_agent_inner(
        self,
        message,
        context_prompt,
        history,
        source,
        session_id,
        **kwargs,
    ):
        store = MemoryStore()
        store.load_from_disk()
        seen["home"] = get_hermes_home()
        seen["memory_dir"] = get_memory_dir()
        seen["memory_entries"] = list(store.memory_entries)
        seen["user_entries"] = list(store.user_entries)
        seen["profile"] = source.profile
        return {"final_response": "ok"}

    monkeypatch.setattr(GatewayRunner, "_run_agent_inner", _fake_run_agent_inner)

    result = await GatewayRunner._run_agent(
        runner,
        message="hello",
        context_prompt="",
        history=[],
        source=_source(profile="principal_shared01", user_id="tg-user"),
        session_id="sess-1",
        session_key="agent:principal_shared01:telegram:dm:tg-user",
    )

    assert result == {"final_response": "ok"}
    assert seen["home"] == profile_home
    assert seen["memory_dir"] == profile_home / "memories"
    assert seen["memory_entries"] == ["shared-memory"]
    assert seen["user_entries"] == ["shared-user"]
    assert seen["profile"] == "principal_shared01"


def test_same_profile_name_resolves_same_home_across_platforms(monkeypatch, tmp_path):
    monkeypatch.setenv("HERMES_HOME", str(tmp_path))
    create_profile("principal_cross001", no_alias=True)
    runner = GatewayRunner.__new__(GatewayRunner)

    telegram_home = runner._resolve_profile_home_for_source(
        _source(profile="principal_cross001", platform=Platform.TELEGRAM, user_id="tg-1")
    )
    line_home = runner._resolve_profile_home_for_source(
        _source(profile= "principal_cross001", platform=Platform("line"), user_id="line-1")
    )
    other_home = runner._resolve_profile_home_for_source(
        _source(profile="principal_other999", platform=Platform.TELEGRAM, user_id="tg-2")
    )

    assert telegram_home == line_home == get_profile_dir("principal_cross001")
    assert other_home == get_profile_dir("principal_other999")
    assert telegram_home != other_home
