from __future__ import annotations

from datetime import UTC, datetime, timedelta

from sqlalchemy import create_engine
from sqlalchemy.orm import Session, sessionmaker
from sqlalchemy.pool import StaticPool

from app.db.base import Base
from app.models.agent_feedback import AgentOperationFeedback
from app.models.agent_run import AgentRun, AgentToolCall
from app.models.user_session_metric import UserSessionMetric
from app.services.system_dashboard import SystemDashboardService


def build_session() -> Session:
    engine = create_engine(
        "sqlite+pysqlite:///:memory:",
        connect_args={"check_same_thread": False},
        poolclass=StaticPool,
    )
    Base.metadata.create_all(bind=engine)
    session_factory = sessionmaker(bind=engine, autoflush=False, autocommit=False)
    return session_factory()


def test_system_dashboard_service_aggregates_real_runtime_metrics() -> None:
    now = datetime.now(UTC)

    with build_session() as db:
        db.add(
            AgentRun(
                run_id="run-dashboard-001",
                agent="orchestrator",
                source="user_message",
                user_id="chen.yuqing@example.com",
                status="succeeded",
                started_at=now - timedelta(hours=3),
                finished_at=now - timedelta(hours=3, minutes=-1),
                tool_calls=[
                    AgentToolCall(
                        run_id="run-dashboard-001",
                        tool_type="llm",
                        tool_name="expense_claim.review",
                        request_json={"prompt_tokens": 120},
                        response_json={"completion_tokens": 80},
                        status="succeeded",
                        duration_ms=1800,
                        created_at=now - timedelta(hours=3),
                    ),
                    AgentToolCall(
                        run_id="run-dashboard-001",
                        tool_type="ocr",
                        tool_name="invoice.ocr",
                        request_json={"image_count": 1},
                        response_json={"message": "识别失败"},
                        status="failed",
                        duration_ms=2600,
                        error_message="low confidence",
                        created_at=now - timedelta(hours=2),
                    ),
                ],
            )
        )
        db.add(
            AgentRun(
                run_id="run-dashboard-002",
                agent="hermes",
                source="schedule",
                user_id="gu.chengyu@example.com",
                status="failed",
                started_at=now - timedelta(hours=1),
                finished_at=now,
                tool_calls=[
                    AgentToolCall(
                        run_id="run-dashboard-002",
                        tool_type="knowledge",
                        tool_name="policy.rag",
                        request_json={"total_tokens": 90},
                        response_json={},
                        status="succeeded",
                        duration_ms=900,
                        created_at=now - timedelta(hours=1),
                    ),
                ],
            )
        )
        db.add_all(
            [
                UserSessionMetric(
                    session_id="session-dashboard-001",
                    username="chen.yuqing@example.com",
                    display_name="陈雨晴",
                    email="chen.yuqing@example.com",
                    login_at=now - timedelta(hours=4),
                    logout_at=now - timedelta(hours=3),
                    duration_ms=60 * 60 * 1000,
                    activity_event_count=16,
                    status="closed",
                ),
                UserSessionMetric(
                    session_id="session-dashboard-002",
                    username="gu.chengyu@example.com",
                    display_name="顾成宇",
                    email="gu.chengyu@example.com",
                    login_at=now - timedelta(minutes=25),
                    last_activity_at=now - timedelta(minutes=5),
                    activity_event_count=9,
                    status="active",
                ),
            ]
        )
        db.add_all(
            [
                AgentOperationFeedback(
                    run_id="run-dashboard-001",
                    user_id="chen.yuqing@example.com",
                    agent="orchestrator",
                    rating=5,
                    created_at=now - timedelta(hours=2),
                ),
                AgentOperationFeedback(
                    run_id="run-dashboard-002",
                    user_id="gu.chengyu@example.com",
                    agent="hermes",
                    rating=2,
                    created_at=now - timedelta(hours=1),
                ),
            ]
        )
        db.commit()

        dashboard = SystemDashboardService(db).build_dashboard(days=7)

        assert dashboard.has_real_data is True
        assert dashboard.totals["toolCalls"] == 3
        assert dashboard.totals["modelTokens"] >= 290
        assert dashboard.totals["onlineUsers"] == 1
        assert dashboard.totals["executionSuccessRate"] == 50.0
        assert dashboard.totals["positiveFeedback"] == 1
        assert dashboard.totals["negativeFeedback"] == 1
        assert dashboard.user_token_usage[0]["tokens"] >= 200
        assert "陈雨晴" in {item["name"] for item in dashboard.user_token_usage}
        assert dashboard.accuracy_comparison["correct"][
            dashboard.accuracy_comparison["categories"].index("报销预审")
        ] == 1
        assert dashboard.accuracy_comparison["wrong"][
            dashboard.accuracy_comparison["categories"].index("异常诊断")
        ] == 1


def test_system_dashboard_counts_online_users_from_active_sessions_across_window() -> None:
    now = datetime.now(UTC)

    with build_session() as db:
        db.add_all(
            [
                UserSessionMetric(
                    session_id="session-online-old-001",
                    username="active.user@example.com",
                    display_name="在线用户",
                    email="active.user@example.com",
                    login_at=now - timedelta(days=2),
                    last_activity_at=now - timedelta(days=2),
                    activity_event_count=3,
                    status="active",
                ),
                UserSessionMetric(
                    session_id="session-online-old-002",
                    username="active.user@example.com",
                    display_name="在线用户",
                    email="active.user@example.com",
                    login_at=now - timedelta(minutes=15),
                    last_activity_at=now - timedelta(minutes=15),
                    activity_event_count=5,
                    status="active",
                ),
                UserSessionMetric(
                    session_id="session-closed-outside-window",
                    username="offline.user@example.com",
                    display_name="离线用户",
                    email="offline.user@example.com",
                    login_at=now - timedelta(days=3),
                    logout_at=now - timedelta(days=2, hours=23),
                    duration_ms=60 * 60 * 1000,
                    status="closed",
                ),
            ]
        )
        db.commit()

        dashboard = SystemDashboardService(db).build_dashboard(days=1)
        login_users = dashboard.login_wave["loginUsers"]

        assert dashboard.totals["onlineUsers"] == 1
        assert max(login_users) == 1
        assert "00:00" in dashboard.login_wave["labels"]
        assert "23:00" in dashboard.login_wave["labels"]
