"""Dashboard sidebar navigation regression tests."""

from __future__ import annotations

import re
from pathlib import Path

import pytest
from fastapi import FastAPI
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from app.api.routes import dashboard as dashboard_routes
from app.core.db import get_db
from app.models.base import Base
from app.models.coverage import Coverage  # noqa: F401
from app.models.engagement import Engagement  # noqa: F401
from app.models.event import Event  # noqa: F401
from app.schemas.engagement import EngagementCreate
from app.services import engagements as engagement_service


def _active_nav_labels(html: str) -> list[str]:
    """Extract labels of sidebar items currently marked active."""
    labels: list[str] = []
    for match in re.finditer(r'<a class="nav-item ([^"]*)" href="[^"]*"[^>]*>([^<]+)</a>', html):
        classes = match.group(1).split()
        label = match.group(2).strip()
        if "active" in classes:
            labels.append(label)
    return labels


@pytest.fixture()
def client(tmp_path: Path) -> TestClient:
    """Build isolated dashboard app with one engagement."""
    db_path = tmp_path / "dashboard_nav_test.db"
    engine = create_engine(
        f"sqlite:///{db_path}",
        connect_args={"check_same_thread": False},
    )
    SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
    Base.metadata.create_all(bind=engine)

    with SessionLocal() as db:
        engagement_service.create_engagement(
            db=db,
            payload=EngagementCreate(name="nav-regression", description="sidebar mapping fixture"),
        )

    app = FastAPI()
    app.include_router(dashboard_routes.router)

    def override_get_db():
        db = SessionLocal()
        try:
            yield db
        finally:
            db.close()

    app.dependency_overrides[get_db] = override_get_db

    with TestClient(app) as test_client:
        yield test_client

    app.dependency_overrides.clear()
    engine.dispose()


def test_sidebar_highlights_exactly_one_item_per_route(client: TestClient) -> None:
    """Each dashboard page should map to exactly one active sidebar section."""
    home = client.get("/")
    assert home.status_code == 200
    assert 'href="/assistant/ui"' not in home.text

    engagement_match = re.search(r"/dashboard/engagement/(\d+)", home.text)
    assert engagement_match is not None
    engagement_id = int(engagement_match.group(1))

    route_expectations = [
        ("/", "Operations"),
        (f"/dashboard/engagement/{engagement_id}", "Operations"),
        (f"/dashboard/report/{engagement_id}", "Reporting"),
        (f"/dashboard/notes/{engagement_id}", "Notes"),
        ("/dashboard/vault", "Vault"),
        ("/dashboard/tasks", "Tasks"),
        ("/dashboard/config", "Config"),
        ("/dashboard/settings", "Config"),
    ]

    for route, expected_label in route_expectations:
        response = client.get(route)
        assert response.status_code == 200
        active_labels = _active_nav_labels(response.text)
        assert active_labels == [expected_label], f"{route} -> {active_labels}"


def test_report_and_notes_shortcuts_route_to_latest_engagement(client: TestClient) -> None:
    """Sidebar shortcut routes should resolve to engagement-specific pages."""
    report_response = client.get("/dashboard/report", follow_redirects=False)
    assert report_response.status_code == 303
    assert report_response.headers["location"].startswith("/dashboard/report/")

    notes_response = client.get("/dashboard/notes", follow_redirects=False)
    assert notes_response.status_code == 303
    assert notes_response.headers["location"].startswith("/dashboard/notes/")
