"""Tests for Routing Control Center & Web Navigation (A24).

Verifies:
1. AutoAssigner.persist_role_chain saves reordered chains to YAML and survives reload.
2. ActionExecutor handles 'save_chain', 'reorder_chain', 'edit_route', 'assign_role'.
3. Model assignment via ActionExecutor('set_model') updates profile and role default.
4. Web client navigation contains exactly 7 primary sections in order.
5. Redundant views (team, providers) are removed from navigation and client script.
"""

from pathlib import Path
from typing import List

import pytest
from antigravity_provider.router.action_handler import ActionExecutor
from antigravity_provider.router.auto_assigner import AutoAssigner
from antigravity_provider.router.router_config import (
    RolePolicy,
    RouterConfig,
    RouterProfileConfig,
    load_router_config,
    save_router_config,
)


@pytest.fixture
def temp_router_config(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
    """Creates an isolated temporary router configuration."""
    cfg_path = tmp_path / "router_profiles.yaml"
    monkeypatch.setenv("HERMES_ROUTER_CONFIG", str(cfg_path))

    # Initialize sample profiles and roles
    config = RouterConfig(
        enabled=True,
        default_role="orchestrator",
        profiles={
            "ag-w1": RouterProfileConfig(
                profile_id="ag-w1",
                provider="antigravity",
                account_id="ag-dev-1",
                preferred_models=["gemini-2.5-pro"],
            ),
            "ag-w2": RouterProfileConfig(
                profile_id="ag-w2",
                provider="antigravity",
                account_id="ag-dev-2",
                preferred_models=["gemini-2.5-flash"],
            ),
            "op-1": RouterProfileConfig(
                profile_id="op-1",
                provider="opencode-go",
                account_id="op-primary",
                preferred_models=["glm-4.7"],
            ),
            "cl-1": RouterProfileConfig(
                profile_id="cl-1",
                provider="claude",
                account_id="cl-fast",
                preferred_models=["claude-3-5-sonnet"],
            ),
        },
        roles={
            "coder-primary": RolePolicy(
                role_name="coder-primary",
                preferred_chain=["ag-w1", "ag-w2", "op-1"],
                default_model="gemini-2.5-pro",
            ),
            "coder-secondary": RolePolicy(
                role_name="coder-secondary",
                preferred_chain=["ag-w2", "op-1"],
                default_model="gemini-2.5-flash",
            ),
        },
    )
    save_router_config(config)
    return cfg_path


def test_persist_role_chain_reorder_and_persistence(temp_router_config: Path):
    """Verify persist_role_chain updates preferred_chain and primary_profile_id and survives reload."""
    new_chain: List[str] = ["op-1", "ag-w2", "ag-w1"]
    ok, msg = AutoAssigner.persist_role_chain("coder-primary", new_chain)

    assert ok is True
    assert "успешно сохранена" in msg

    # Reload from disk
    reloaded = load_router_config()
    role_cfg = reloaded.roles["coder-primary"]
    assert role_cfg.preferred_chain == new_chain
    assert role_cfg.preferred_chain[0] == "op-1"


def test_persist_role_chain_canonical_name_mapping(temp_router_config: Path):
    """Verify persist_role_chain resolves Russian aliases and canonical names."""
    new_chain = ["ag-w2", "ag-w1"]
    ok, msg = AutoAssigner.persist_role_chain("кодер 1", new_chain)

    assert ok is True
    reloaded = load_router_config()
    assert reloaded.roles["coder-primary"].preferred_chain == new_chain


def test_persist_role_chain_validation_errors(temp_router_config: Path):
    """Verify persist_role_chain rejects invalid profiles and duplicates."""
    # Unknown profile
    ok, msg = AutoAssigner.persist_role_chain("coder-primary", ["ag-w1", "non-existent-profile"])
    assert ok is False
    assert "не найден" in msg

    # Duplicate profile in chain
    ok, msg = AutoAssigner.persist_role_chain("coder-primary", ["ag-w1", "ag-w1"])
    assert ok is False
    assert "повторяться" in msg or "дублир" in msg

    # Non-existent role
    ok, msg = AutoAssigner.persist_role_chain("unknown-role-xyz", ["ag-w1"])
    assert ok is False
    assert "Неизвестная роль" in msg or "неизвестн" in msg.lower()


def test_action_executor_save_chain(temp_router_config: Path):
    """Verify ActionExecutor executes 'save_chain', 'reorder_chain', and 'edit_route'."""
    executor = ActionExecutor()

    # save_chain
    res1 = executor.execute("save_chain", {"role_id": "coder-primary", "chain": ["ag-w2", "ag-w1"]})
    assert res1["ok"] is True

    # reorder_chain
    res2 = executor.execute("reorder_chain", {"role_id": "coder-primary", "desired_chain": ["op-1", "ag-w1"]})
    assert res2["ok"] is True

    # edit_route
    res3 = executor.execute("edit_route", {"role_id": "coder-secondary", "chain": ["op-1", "ag-w2"]})
    assert res3["ok"] is True

    reloaded = load_router_config()
    assert reloaded.roles["coder-primary"].preferred_chain == ["op-1", "ag-w1"]
    assert reloaded.roles["coder-secondary"].preferred_chain == ["op-1", "ag-w2"]


def test_action_executor_set_model_updates_profile_and_role(temp_router_config: Path):
    """Verify ActionExecutor('set_model') updates profile preferred_models and role default_model."""
    executor = ActionExecutor()

    res = executor.execute("set_model", {
        "profile_id": "ag-w1",
        "model": "gemini-3.1-pro",
        "role_id": "coder-primary",
    })
    assert res["ok"] is True

    reloaded = load_router_config()
    assert reloaded.profiles["ag-w1"].preferred_models[0] == "gemini-3.1-pro"
    assert reloaded.roles["coder-primary"].default_model == "gemini-3.1-pro"


def test_web_client_7_views_exact_order_and_no_redundant_views():
    """Verify index.html navigation items match exactly 7 sections in required order."""
    static_dir = Path(__file__).parent.parent / "src" / "antigravity_provider" / "router" / "web" / "static"
    index_html = (static_dir / "index.html").read_text(encoding="utf-8")
    app_js = (static_dir / "app.js").read_text(encoding="utf-8")

    expected_views = [
        "overview",
        "accounts",
        "routing",
        "analytics",
        "health",
        "logs",
        "settings",
    ]

    # Verify presence in exact order in index.html nav-menu
    nav_positions = [index_html.find(f'data-view="{v}"') for v in expected_views]
    assert all(pos != -1 for pos in nav_positions), "All 7 views must be present in index.html"
    assert nav_positions == sorted(nav_positions), "Views in index.html must be in exact specified order"

    # Verify absence of removed views
    assert 'data-view="providers"' not in index_html
    assert 'data-view="team"' not in index_html
    assert "renderProvidersView" not in app_js
    assert "renderTeamView" not in app_js
