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_run import AgentRun, AgentToolCall
from app.services.digital_employee_dashboard import DigitalEmployeeDashboardService


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_digital_employee_dashboard_aggregates_daily_work_from_agent_runs() -> None:
    now = datetime.now(UTC)

    with build_session() as db:
        db.add_all(
            [
                AgentRun(
                    run_id="run-digital-risk-001",
                    agent="hermes",
                    source="schedule",
                    user_id="system",
                    status="succeeded",
                    route_json={
                        "tenant_id": "default",
                        "task_code": "task.hermes.global_risk_scan",
                    },
                    ontology_json={"tenant_id": "default"},
                    result_summary="财务风险图谱巡检完成。",
                    started_at=now - timedelta(hours=4),
                    finished_at=now - timedelta(hours=4, minutes=-3),
                    tool_calls=[
                        AgentToolCall(
                            run_id="run-digital-risk-001",
                            tool_type="rule_engine",
                            tool_name="digital_employee.financial_risk_graph.scan",
                            request_json={"task_type": "global_risk_scan"},
                            response_json={
                                "scanned_claim_count": 18,
                                "risk_observation_count": 3,
                            },
                            status="succeeded",
                            duration_ms=1200,
                            created_at=now - timedelta(hours=4),
                        )
                    ],
                ),
                AgentRun(
                    run_id="run-digital-clue-001",
                    agent="hermes",
                    source="schedule",
                    user_id="system",
                    status="failed",
                    route_json={
                        "tenant_id": "default",
                        "report_type": "risk_clue_collect",
                    },
                    ontology_json={"tenant_id": "default"},
                    result_summary="风险线索归集失败。",
                    started_at=now - timedelta(hours=3),
                    finished_at=now - timedelta(hours=3, minutes=-1),
                    tool_calls=[
                        AgentToolCall(
                            run_id="run-digital-clue-001",
                            tool_type="database",
                            tool_name="digital_employee.risk_clue.collect",
                            request_json={"task_type": "risk_clue_collect"},
                            response_json={
                                "fact_count": 12,
                                "rule_hit_count": 5,
                                "risk_clue_count": 2,
                            },
                            status="failed",
                            duration_ms=800,
                            error_message="collector failed",
                            created_at=now - timedelta(hours=3),
                        )
                    ],
                ),
                AgentRun(
                    run_id="run-digital-knowledge-001",
                    agent="hermes",
                    source="user_message",
                    user_id="admin",
                    status="running",
                    route_json={
                        "tenant_id": "default",
                        "job_type": "knowledge_index_sync",
                        "requested_document_ids": ["doc-1", "doc-2"],
                    },
                    ontology_json={"tenant_id": "default"},
                    result_summary="知识归纳任务已入队。",
                    started_at=now - timedelta(hours=1),
                ),
                AgentRun(
                    run_id="run-user-001",
                    agent="user_agent",
                    source="user_message",
                    user_id="employee",
                    status="succeeded",
                    result_summary="普通报销预审。",
                    started_at=now - timedelta(hours=2),
                    finished_at=now - timedelta(hours=2, minutes=-1),
                    tool_calls=[
                        AgentToolCall(
                            run_id="run-user-001",
                            tool_type="llm",
                            tool_name="expense_claim.review",
                            request_json={},
                            response_json={},
                            status="succeeded",
                            duration_ms=500,
                            created_at=now - timedelta(hours=2),
                        )
                    ],
                ),
            ]
        )
        db.commit()

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

        assert dashboard.has_real_data is True
        assert dashboard.totals["totalRuns"] == 3
        assert dashboard.totals["successRuns"] == 1
        assert dashboard.totals["failedRuns"] == 1
        assert dashboard.totals["runningRuns"] == 1
        assert dashboard.totals["toolCalls"] == 2
        assert dashboard.totals["riskObservations"] == 3
        assert dashboard.totals["riskClues"] == 2
        assert dashboard.totals["knowledgeDocuments"] == 2
        assert dashboard.totals["businessOutputs"] == 7
        assert dashboard.totals["successRate"] == 33.3

        category_counts = {item["name"]: item["count"] for item in dashboard.category_distribution}
        assert category_counts["评估"] == 1
        assert category_counts["升级"] == 1
        assert category_counts["整理"] == 1
        assert category_counts["积累"] == 0

        task_names = {item["name"] for item in dashboard.task_distribution}
        assert task_names == {"财务风险图谱巡检", "风险线索归集", "知识制度整理"}

        assert sum(item["total"] for item in dashboard.daily_work) == 3
        assert dashboard.recent_runs[0]["runId"] == "run-digital-knowledge-001"
        assert dashboard.recent_runs[0]["statusLabel"] == "运行中"


def test_digital_employee_dashboard_keeps_empty_payload_without_fake_data() -> None:
    with build_session() as db:
        dashboard = DigitalEmployeeDashboardService(db).build_dashboard(days=7)

        assert dashboard.has_real_data is False
        assert dashboard.totals["totalRuns"] == 0
        assert dashboard.daily_work
        assert dashboard.task_distribution == []


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

    with build_session() as db:
        db.add(
            AgentRun(
                run_id="run-finance-snapshot-001",
                agent="hermes",
                source="schedule",
                user_id="digital_employee",
                status="succeeded",
                route_json={
                    "tenant_id": "default",
                    "task_type": "finance_dashboard_snapshot",
                },
                ontology_json={"tenant_id": "default"},
                result_summary="finance dashboard snapshot generated",
                started_at=now - timedelta(minutes=3),
                finished_at=now - timedelta(minutes=2),
                tool_calls=[
                    AgentToolCall(
                        run_id="run-finance-snapshot-001",
                        tool_type="database",
                        tool_name="digital_employee.finance_dashboard.snapshot",
                        request_json={"task_type": "finance_dashboard_snapshot"},
                        response_json={
                            "summary": {
                                "finance_snapshot_count": 1,
                                "reimbursement_count": 534,
                            }
                        },
                        status="succeeded",
                        duration_ms=1200,
                        created_at=now - timedelta(minutes=3),
                    )
                ],
            )
        )
        db.commit()

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

        assert dashboard.totals["financeDashboardSnapshots"] == 1
        assert dashboard.totals["businessOutputs"] == 1
        assert dashboard.daily_work[-1]["financeDashboardSnapshots"] == 1
        assert dashboard.task_distribution[0]["taskType"] == "finance_dashboard_snapshot"


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

    with build_session() as db:
        db.add(
            AgentRun(
                run_id="run-reminder-scan-001",
                agent="hermes",
                source="schedule",
                user_id="digital_employee",
                status="succeeded",
                route_json={
                    "tenant_id": "default",
                    "task_type": "digital_employee_reminder_scan",
                },
                ontology_json={"tenant_id": "default"},
                result_summary="reminder scan generated",
                started_at=now - timedelta(minutes=3),
                finished_at=now - timedelta(minutes=2),
                tool_calls=[
                    AgentToolCall(
                        run_id="run-reminder-scan-001",
                        tool_type="database",
                        tool_name="digital_employee.reminder.scan",
                        request_json={"task_type": "digital_employee_reminder_scan"},
                        response_json={
                            "summary": {
                                "recipient_count": 3,
                                "reminder_count": 8,
                                "approval_pending_count": 2,
                            }
                        },
                        status="succeeded",
                        duration_ms=900,
                        created_at=now - timedelta(minutes=3),
                    )
                ],
            )
        )
        db.commit()

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

        assert dashboard.totals["reminders"] == 8
        assert dashboard.totals["businessOutputs"] == 8
        assert dashboard.daily_work[-1]["reminders"] == 8
        assert dashboard.task_distribution[0]["taskType"] == "digital_employee_reminder_scan"
