"""Unit tests for config snapshot management."""

from sqlmodel import Session, select

from agenteval.intelligent_eval import config_snapshot
from agenteval.storage.db import IntelligentEvalConfigSnapshotDB, IntelligentEvalDB


def test_save_snapshot_created(db_session: Session):
    """Test saving a snapshot when eval is created."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        goal="test goal",
        intent="test intent",
        role_description="test role",
        time_window_hours=24,
    )
    eval_db.set_seeds({"personas": ["user1"]})
    db_session.add(eval_db)
    db_session.commit()

    snapshot = config_snapshot.save_snapshot(eval_db, "created", "user", db_session)

    assert snapshot.eval_id == eval_db.id
    assert snapshot.snapshot_type == "created"
    assert snapshot.goal == "test goal"
    assert snapshot.intent == "test intent"
    assert snapshot.role_description == "test role"
    assert snapshot.time_window_hours == 24
    assert snapshot.get_seeds() == {"personas": ["user1"]}
    assert snapshot.created_by == "user"


def test_save_snapshot_plan_submitted(db_session: Session):
    """Test saving a snapshot when plan is submitted."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        goal="test goal",
    )
    plan = {"dimensions": ["dim1"], "estimated_sessions": 5}
    eval_db.set_plan(plan)
    db_session.add(eval_db)
    db_session.commit()

    snapshot = config_snapshot.save_snapshot(eval_db, "plan_submitted", "openclaw", db_session)

    assert snapshot.snapshot_type == "plan_submitted"
    assert snapshot.get_plan() == plan
    assert snapshot.created_by == "openclaw"


def test_list_snapshots(db_session: Session):
    """Test listing snapshots for an eval."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        goal="goal1",
    )
    db_session.add(eval_db)
    db_session.commit()

    # Create 3 snapshots
    snapshot1 = config_snapshot.save_snapshot(eval_db, "created", "user", db_session)

    eval_db.goal = "goal2"
    db_session.commit()
    snapshot2 = config_snapshot.save_snapshot(eval_db, "config_updated", "user", db_session)

    eval_db.goal = "goal3"
    db_session.commit()
    snapshot3 = config_snapshot.save_snapshot(eval_db, "config_updated", "user", db_session)

    snapshots = config_snapshot.list_snapshots(eval_db.id, db_session)

    assert len(snapshots) == 3
    # Should be ordered by created_at descending (newest first)
    assert snapshots[0].id == snapshot3.id
    assert snapshots[1].id == snapshot2.id
    assert snapshots[2].id == snapshot1.id


def test_get_snapshot(db_session: Session):
    """Test getting a single snapshot."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        goal="test goal",
    )
    db_session.add(eval_db)
    db_session.commit()

    snapshot = config_snapshot.save_snapshot(eval_db, "created", "user", db_session)

    retrieved = config_snapshot.get_snapshot(snapshot.id, db_session)
    assert retrieved is not None
    assert retrieved.id == snapshot.id
    assert retrieved.goal == "test goal"


def test_get_snapshot_not_found(db_session: Session):
    """Test getting a non-existent snapshot."""
    snapshot = config_snapshot.get_snapshot("nonexistent", db_session)
    assert snapshot is None


def test_compare_snapshots_simple_fields(db_session: Session):
    """Test comparing snapshots with different simple fields."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        goal="goal1",
        intent="intent1",
    )
    db_session.add(eval_db)
    db_session.commit()

    snapshot1 = config_snapshot.save_snapshot(eval_db, "created", "user", db_session)

    # Update fields
    eval_db.goal = "goal2"
    eval_db.intent = "intent2"
    db_session.commit()

    snapshot2 = config_snapshot.save_snapshot(eval_db, "config_updated", "user", db_session)

    diffs = config_snapshot.compare_snapshots(snapshot1, snapshot2)

    assert "goal" in diffs
    assert diffs["goal"]["old"] == "goal1"
    assert diffs["goal"]["new"] == "goal2"

    assert "intent" in diffs
    assert diffs["intent"]["old"] == "intent1"
    assert diffs["intent"]["new"] == "intent2"


def test_compare_snapshots_json_fields(db_session: Session):
    """Test comparing snapshots with different JSON fields."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
    )
    eval_db.set_seeds({"personas": ["user1"]})
    db_session.add(eval_db)
    db_session.commit()

    snapshot1 = config_snapshot.save_snapshot(eval_db, "created", "user", db_session)

    # Update seeds
    eval_db.set_seeds({"personas": ["user1", "user2"]})
    db_session.commit()

    snapshot2 = config_snapshot.save_snapshot(eval_db, "config_updated", "user", db_session)

    diffs = config_snapshot.compare_snapshots(snapshot1, snapshot2)

    assert "seeds" in diffs
    assert diffs["seeds"]["old"] == {"personas": ["user1"]}
    assert diffs["seeds"]["new"] == {"personas": ["user1", "user2"]}


def test_compare_snapshots_no_differences(db_session: Session):
    """Test comparing identical snapshots."""
    eval_db = IntelligentEvalDB(
        name="test",
        target_id="target1",
        goal="goal1",
    )
    db_session.add(eval_db)
    db_session.commit()

    snapshot1 = config_snapshot.save_snapshot(eval_db, "created", "user", db_session)
    snapshot2 = config_snapshot.save_snapshot(eval_db, "created", "user", db_session)

    diffs = config_snapshot.compare_snapshots(snapshot1, snapshot2)

    assert diffs == {}
