"""Unit tests for worker decision logic."""

from datetime import timedelta

import pytest
from sqlmodel import Session

from agenteval.intelligent_eval.decision import DecisionType, is_eval_completed, make_decision
from agenteval.intelligent_eval.models import IntelligentEvalStatus
from agenteval.storage.db import IntelligentEvalDB, IntelligentEvalSessionDB, utc_now


def test_decision_wait_not_executing(db_session: Session):
    """Test decision is WAIT when eval is not executing."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.COMPLETED.value,
    )
    db_session.add(eval_db)
    db_session.commit()

    decision = make_decision(eval_db, db_session)
    assert decision.decision_type == DecisionType.WAIT
    assert "不在执行中" in decision.reason


def test_decision_wait_no_plan(db_session: Session):
    """Test decision is WAIT when eval has no plan."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
        started_at=utc_now(),
    )
    db_session.add(eval_db)
    db_session.commit()

    decision = make_decision(eval_db, db_session)
    assert decision.decision_type == DecisionType.WAIT
    assert "缺少计划" in decision.reason


def test_decision_start_analysis_all_completed(db_session: Session):
    """Test decision is START_ANALYSIS when all sessions completed."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
        started_at=utc_now() - timedelta(hours=10),
    )
    eval_db.set_plan({
        "time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
        "estimated_sessions": 2,
    })
    db_session.add(eval_db)
    db_session.commit()

    # Add 2 completed sessions
    for _ in range(2):
        session_db = IntelligentEvalSessionDB(
            eval_id=eval_db.id,
            target_id="target1",
            status="completed",
        )
        db_session.add(session_db)
    db_session.commit()

    decision = make_decision(eval_db, db_session)
    assert decision.decision_type == DecisionType.START_ANALYSIS
    assert "所有 2 个会话已完成" in decision.reason


def test_decision_execute_session_slot_deficit(db_session: Session):
    """Test decision is EXECUTE_SESSION when current slot has deficit."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
        started_at=utc_now() - timedelta(hours=8, minutes=30),  # 8.5 hours ago
    )
    eval_db.set_plan({
        "time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
        "estimated_sessions": 2,
    })
    db_session.add(eval_db)
    db_session.commit()

    # Add 1 session created within the 8-10h slot (deficit = 1)
    # Slot starts at started_at + 8h = 0.5h ago
    session_db = IntelligentEvalSessionDB(
        eval_id=eval_db.id,
        target_id="target1",
        status="running",
        created_at=utc_now() - timedelta(minutes=20),  # 20 minutes ago, within slot
    )
    db_session.add(session_db)
    db_session.commit()

    decision = make_decision(eval_db, db_session)
    assert decision.decision_type == DecisionType.EXECUTE_SESSION
    assert "欠账 1 个会话" in decision.reason
    assert decision.context["current_slot"] == "8-10h"
    assert decision.context["deficit"] == 1


def test_decision_execute_session_high_severity(db_session: Session):
    """Test decision is EXECUTE_SESSION when high severity issue found."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
        started_at=utc_now() - timedelta(hours=8, minutes=30),
    )
    eval_db.set_plan({
        "time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
        "estimated_sessions": 3,  # Not all completed yet
    })
    db_session.add(eval_db)
    db_session.commit()

    # Add 2 completed sessions within the slot (no deficit)
    for _ in range(2):
        session_db = IntelligentEvalSessionDB(
            eval_id=eval_db.id,
            target_id="target1",
            status="completed",
            created_at=utc_now() - timedelta(minutes=20),  # Within slot
        )
        # One with high severity
        session_db.set_verdict({"severity": "high", "issues": ["critical bug"]})
        db_session.add(session_db)
    db_session.commit()

    decision = make_decision(eval_db, db_session)
    assert decision.decision_type == DecisionType.EXECUTE_SESSION
    assert "高严重度问题" in decision.reason


def test_decision_wait_no_deficit(db_session: Session):
    """Test decision is WAIT when no deficit in current slot."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
        started_at=utc_now() - timedelta(hours=8, minutes=30),
    )
    eval_db.set_plan({
        "time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
        "estimated_sessions": 3,  # Not all completed yet
    })
    db_session.add(eval_db)
    db_session.commit()

    # Add 2 sessions within the slot (no deficit)
    for _ in range(2):
        session_db = IntelligentEvalSessionDB(
            eval_id=eval_db.id,
            target_id="target1",
            status="running",
            created_at=utc_now() - timedelta(minutes=20),  # Within slot
        )
        db_session.add(session_db)
    db_session.commit()

    decision = make_decision(eval_db, db_session)
    assert decision.decision_type == DecisionType.WAIT
    assert "无欠账" in decision.reason


def test_decision_wait_outside_slots(db_session: Session):
    """Test decision is WAIT when current time is outside all slots."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
        started_at=utc_now() - timedelta(hours=5),  # 5 hours ago, outside 8-10h
    )
    eval_db.set_plan({
        "time_distribution": [{"time_slot": "8-10h", "sessions": 2}],
        "estimated_sessions": 2,
    })
    db_session.add(eval_db)
    db_session.commit()

    decision = make_decision(eval_db, db_session)
    assert decision.decision_type == DecisionType.WAIT
    assert "不在任何时段内" in decision.reason


def test_is_eval_completed_not_executing(db_session: Session):
    """Test is_eval_completed returns False when eval is not executing."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.COMPLETED.value,
    )
    db_session.add(eval_db)
    db_session.commit()

    assert is_eval_completed(eval_db, db_session) is False


def test_is_eval_completed_no_plan(db_session: Session):
    """Test is_eval_completed returns False when eval has no plan."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
    )
    db_session.add(eval_db)
    db_session.commit()

    assert is_eval_completed(eval_db, db_session) is False


def test_is_eval_completed_sessions_not_finished(db_session: Session):
    """Test is_eval_completed returns False when not all sessions completed."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
    )
    eval_db.set_plan({"estimated_sessions": 2})
    db_session.add(eval_db)
    db_session.commit()

    # Add only 1 completed session
    session_db = IntelligentEvalSessionDB(
        eval_id=eval_db.id,
        target_id="target1",
        status="completed",
    )
    db_session.add(session_db)
    db_session.commit()

    assert is_eval_completed(eval_db, db_session) is False


def test_is_eval_completed_no_report(db_session: Session):
    """Test is_eval_completed returns False when report not submitted."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
    )
    eval_db.set_plan({"estimated_sessions": 2})
    db_session.add(eval_db)
    db_session.commit()

    # Add 2 completed sessions
    for _ in range(2):
        session_db = IntelligentEvalSessionDB(
            eval_id=eval_db.id,
            target_id="target1",
            status="completed",
        )
        db_session.add(session_db)
    db_session.commit()

    assert is_eval_completed(eval_db, db_session) is False


def test_is_eval_completed_true(db_session: Session):
    """Test is_eval_completed returns True when all conditions met."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        status=IntelligentEvalStatus.EXECUTING.value,
    )
    eval_db.set_plan({"estimated_sessions": 2})
    eval_db.set_report({"summary": "test report"})
    db_session.add(eval_db)
    db_session.commit()

    # Add 2 completed sessions
    for _ in range(2):
        session_db = IntelligentEvalSessionDB(
            eval_id=eval_db.id,
            target_id="target1",
            status="completed",
        )
        db_session.add(session_db)
    db_session.commit()

    assert is_eval_completed(eval_db, db_session) is True
