"""Step definitions for TUI session persistence."""

from __future__ import annotations

import tempfile
from pathlib import Path

from behave import given, then, when

from cleveragents.tui.app import SessionView
from cleveragents.tui.persistence import TuiSessionStore


@given("a clean TUI session database")
def step_clean_database(context: object) -> None:
    """Create a clean temporary database for testing."""
    # Create a temporary directory for the test database
    temp_dir = tempfile.mkdtemp()
    db_path = Path(temp_dir) / "tui.db"

    # Store in context for later use
    context.temp_dir = temp_dir  # type: ignore
    context.db_path = db_path  # type: ignore
    context.store = TuiSessionStore(db_path=db_path)  # type: ignore


@when("the TUI session store is initialized")
def step_initialize_store(context: object) -> None:
    """Initialize the session store (already done in background)."""
    pass


@then("the SQLite database file exists at ~/.local/state/cleveragents/tui.db")
def step_database_exists(context: object) -> None:
    """Verify the database file exists."""
    assert context.db_path.exists()  # type: ignore


@then("the database has sessions and active_session tables")
def step_database_has_tables(context: object) -> None:
    """Verify the database has the required tables."""
    import sqlite3

    with sqlite3.connect(context.db_path) as conn:  # type: ignore
        cursor = conn.execute("SELECT name FROM sqlite_master WHERE type='table'")
        tables = {row[0] for row in cursor.fetchall()}
        assert "sessions" in tables
        assert "active_session" in tables


@given('a session with id "{session_id}" and transcript {transcript}')
def step_create_session_with_transcript(
    context: object, session_id: str, transcript: str
) -> None:
    """Create a session with the given id and transcript."""
    # Parse the transcript list from the string
    import ast

    transcript_list = ast.literal_eval(transcript)
    session = SessionView(session_id=session_id, transcript=transcript_list)
    context.session = session  # type: ignore


@given('a session with id "{session_id}"')
def step_create_session(context: object, session_id: str) -> None:
    """Create a session with the given id."""
    session = SessionView(session_id=session_id, transcript=[])
    context.session = session  # type: ignore


@when("I save the session to the database")
def step_save_session(context: object) -> None:
    """Save the session to the database."""
    context.store.save_session(context.session)  # type: ignore


@then("the session can be loaded from the database")
def step_load_session(context: object) -> None:
    """Load the session from the database."""
    loaded = context.store.load_session(context.session.session_id)  # type: ignore
    assert loaded is not None
    context.loaded_session = loaded  # type: ignore


@then("the loaded session has the same id and transcript")
def step_verify_session_data(context: object) -> None:
    """Verify the loaded session matches the original."""
    assert context.loaded_session.session_id == context.session.session_id  # type: ignore
    assert context.loaded_session.transcript == context.session.transcript  # type: ignore


@when("I set it as the active session")
def step_set_active_session(context: object) -> None:
    """Set the session as active."""
    context.store.set_active_session(context.session.session_id)  # type: ignore


@then('the active session id is "{session_id}"')
def step_verify_active_session(context: object, session_id: str) -> None:
    """Verify the active session id."""
    active = context.store.get_active_session()  # type: ignore
    assert active == session_id


@given("sessions with ids {session_ids}")
def step_create_multiple_sessions(context: object, session_ids: str) -> None:
    """Create multiple sessions."""
    import ast

    ids = ast.literal_eval(session_ids)
    context.sessions = [  # type: ignore
        SessionView(session_id=sid, transcript=[]) for sid in ids
    ]


@when("I save all sessions to the database")
def step_save_all_sessions(context: object) -> None:
    """Save all sessions to the database."""
    for session in context.sessions:  # type: ignore
        context.store.save_session(session)  # type: ignore


@then("listing sessions returns all three session ids")
def step_verify_list_sessions(context: object) -> None:
    """Verify all sessions are listed."""
    listed = context.store.list_sessions()  # type: ignore
    expected_ids = {s.session_id for s in context.sessions}  # type: ignore
    assert set(listed) == expected_ids


@given('a session with id "{session_id}" in the database')
def step_create_and_save_session(context: object, session_id: str) -> None:
    """Create and save a session."""
    session = SessionView(session_id=session_id, transcript=[])
    context.store.save_session(session)  # type: ignore
    context.session = session  # type: ignore


@when("I delete the session")
def step_delete_session(context: object) -> None:
    """Delete the session."""
    context.store.delete_session(context.session.session_id)  # type: ignore


@then("the session can no longer be loaded from the database")
def step_verify_session_deleted(context: object) -> None:
    """Verify the session is deleted."""
    loaded = context.store.load_session(context.session.session_id)  # type: ignore
    assert loaded is None


@when("I clear all sessions")
def step_clear_all_sessions(context: object) -> None:
    """Clear all sessions."""
    context.store.clear_all()  # type: ignore


@then("the database has no sessions")
def step_verify_no_sessions(context: object) -> None:
    """Verify there are no sessions."""
    listed = context.store.list_sessions()  # type: ignore
    assert len(listed) == 0


@then("there is no active session")
def step_verify_no_active_session(context: object) -> None:
    """Verify there is no active session."""
    active = context.store.get_active_session()  # type: ignore
    assert active is None


@when("I save the session and set it as active")
def step_save_and_set_active(context: object) -> None:
    """Save the session and set it as active."""
    context.store.save_session(context.session)  # type: ignore
    context.store.set_active_session(context.session.session_id)  # type: ignore


@when("I create a new session store instance")
def step_create_new_store_instance(context: object) -> None:
    """Create a new session store instance."""
    context.new_store = TuiSessionStore(db_path=context.db_path)  # type: ignore


@then('the active session is "{session_id}"')
def step_verify_new_store_active_session(context: object, session_id: str) -> None:
    """Verify the active session in the new store."""
    active = context.new_store.get_active_session()  # type: ignore
    assert active == session_id


@then("the session data is restored correctly")
def step_verify_session_restored(context: object) -> None:
    """Verify the session data is restored correctly."""
    loaded = context.new_store.load_session(context.session.session_id)  # type: ignore
    assert loaded is not None
    assert loaded.session_id == context.session.session_id  # type: ignore
    assert loaded.transcript == context.session.transcript  # type: ignore


@given("the TUI session store is created with default database path")
def step_default_db_path(context: object) -> None:
    """Initialize store using the default path, patching home to a temp dir."""
    from unittest.mock import patch

    temp_dir = tempfile.mkdtemp()
    temp_home = Path(temp_dir)
    with patch.object(Path, "home", return_value=temp_home):
        context.store = TuiSessionStore()  # type: ignore
    context.db_path = (  # type: ignore
        temp_home / ".local" / "state" / "cleveragents" / "tui.db"
    )
