"""
Testy main.py — ładowanie/zapis konfiguracji oraz integracja on_change z Orchestratorem.
"""

import json

import pytest

from main import load_config, save_config
from ..connection_pool import ConnectionPool
from ..executor import Executor
from ..models import Backend
from ..orchestrator import Orchestrator
from ..registry import Registry


# --- load_config ---

def test_load_config_reads_file(tmp_path):
    config = {"host": "0.0.0.0", "port": 9000, "backends": [{"id": "a", "url": "http://x/mcp/"}]}
    path = tmp_path / "config.json"
    path.write_text(json.dumps(config))

    result = load_config(str(path))

    assert result["host"] == "0.0.0.0"
    assert result["port"] == 9000
    assert result["backends"][0]["id"] == "a"


def test_load_config_missing_file_raises(tmp_path):
    with pytest.raises(FileNotFoundError):
        load_config(str(tmp_path / "nonexistent.json"))


# --- save_config ---

def test_save_config_writes_backends(tmp_path):
    path = tmp_path / "config.json"
    config = {"host": "127.0.0.1", "port": 8000, "backends": []}
    registry = Registry()
    registry.add_backend(Backend(id="dom", url="http://localhost:8123/mcp/"))
    registry.add_backend(Backend(id="user", url="http://localhost:8124/mcp/"))

    save_config(str(path), config, registry)

    saved = json.loads(path.read_text())
    ids = [b["id"] for b in saved["backends"]]
    assert "dom" in ids
    assert "user" in ids


def test_save_config_preserves_host_and_port(tmp_path):
    path = tmp_path / "config.json"
    config = {"host": "0.0.0.0", "port": 9999, "backends": []}
    registry = Registry()

    save_config(str(path), config, registry)

    saved = json.loads(path.read_text())
    assert saved["host"] == "0.0.0.0"
    assert saved["port"] == 9999


def test_save_config_removes_deleted_backend(tmp_path):
    path = tmp_path / "config.json"
    config = {"host": "127.0.0.1", "port": 8000, "backends": []}
    registry = Registry()
    registry.add_backend(Backend(id="dom", url="http://localhost:8123/mcp/"))

    save_config(str(path), config, registry)
    assert len(json.loads(path.read_text())["backends"]) == 1

    registry.remove_backend("dom")
    save_config(str(path), config, registry)
    assert json.loads(path.read_text())["backends"] == []


# --- integracja: on_change odpala zapis po add/remove_backend ---

@pytest.mark.anyio
async def test_on_change_called_after_add_backend(tmp_path, mcp_server_url):
    path = tmp_path / "config.json"
    config = {"host": "127.0.0.1", "port": 8000, "backends": []}
    path.write_text(json.dumps(config))

    registry = Registry()
    pool = ConnectionPool()
    executor = Executor(pool)
    orchestrator = Orchestrator(
        registry, pool, executor,
        on_change=lambda: save_config(str(path), config, registry),
    )

    await orchestrator.add_backend("test", mcp_server_url)

    saved = json.loads(path.read_text())
    assert saved["backends"] == [{"id": "test", "url": mcp_server_url, "enabled": True}]
    await pool.close_all()


@pytest.mark.anyio
async def test_on_change_called_after_remove_backend(tmp_path, mcp_server_url):
    path = tmp_path / "config.json"
    config = {"host": "127.0.0.1", "port": 8000, "backends": []}
    path.write_text(json.dumps(config))

    registry = Registry()
    pool = ConnectionPool()
    executor = Executor(pool)
    orchestrator = Orchestrator(
        registry, pool, executor,
        on_change=lambda: save_config(str(path), config, registry),
    )

    await orchestrator.add_backend("test", mcp_server_url)
    await orchestrator.remove_backend("test")

    saved = json.loads(path.read_text())
    assert saved["backends"] == []
