"""Step definitions for TDD Bug #4739 — TUI SQLite session persistence not implemented.

These steps verify that ``cleveragents.tui.session_store`` exists and that
``TuiSessionStore`` can persist and retrieve session records from SQLite.

All scenarios are tagged ``@tdd_expected_fail`` so CI passes while the
module is absent.  The expected-fail mechanism inverts the result: a
failing assertion means the bug is still present (CI passes); a passing
assertion means the fix has been applied (CI also passes after the
``@tdd_expected_fail`` tag is removed in the bugfix PR).

Failure mode: ``AssertionError`` (not ``ImportError`` or ``RuntimeError``).
"""

from __future__ import annotations

import importlib
import os
import shutil
import tempfile
import types
from typing import Any, cast

from behave import given, then, when
from behave.runner import Context


@given("the tdd4739 test environment is set up")
def step_tdd4739_setup(context: Context) -> None:
    """Initialise context attributes used across tdd4739 steps."""
    context.tdd4739_module: types.ModuleType | None = None
    context.tdd4739_import_error: Exception | None = None
    context.tdd4739_store: object | None = None
    context.tdd4739_tmpdir: str | None = None


@given("the tdd4739 test environment is set up with a temp db path")
def step_tdd4739_setup_with_tmpdir(context: Context) -> None:
    """Initialise context and create a temporary directory for the SQLite db."""
    context.tdd4739_module = None
    context.tdd4739_import_error = None
    context.tdd4739_store = None

    tmpdir = tempfile.mkdtemp(prefix="tdd4739_")
    context.tdd4739_tmpdir = tmpdir
    context.tdd4739_db_path = os.path.join(tmpdir, "tui.db")

    def _cleanup() -> None:
        shutil.rmtree(tmpdir, ignore_errors=True)

    context.add_cleanup(_cleanup)


@when("I attempt to import cleveragents.tui.session_store")
def step_tdd4739_import(context: Context) -> None:
    """Attempt to import the session_store module; capture any ImportError."""
    try:
        mod = importlib.import_module("cleveragents.tui.session_store")
        context.tdd4739_module = mod
        context.tdd4739_import_error = None
    except ImportError as exc:
        context.tdd4739_module = None
        context.tdd4739_import_error = exc


@then("the tdd4739 import should succeed without errors")
def step_tdd4739_import_ok(context: Context) -> None:
    """Assert the import succeeded — fails via AssertionError if module is absent."""
    assert context.tdd4739_import_error is None, (
        f"cleveragents.tui.session_store could not be imported: "
        f"{context.tdd4739_import_error}"
    )
    assert context.tdd4739_module is not None, (
        "cleveragents.tui.session_store module is None after import"
    )


@then("the tdd4739 module should expose a TuiSessionStore class")
def step_tdd4739_class_exists(context: Context) -> None:
    """Assert TuiSessionStore is present in the module."""
    assert context.tdd4739_import_error is None, (
        f"cleveragents.tui.session_store could not be imported: "
        f"{context.tdd4739_import_error}"
    )
    mod = context.tdd4739_module
    assert mod is not None, "session_store module is None"
    assert hasattr(mod, "TuiSessionStore"), (
        "cleveragents.tui.session_store does not expose a TuiSessionStore class"
    )


@when("I create a TuiSessionStore pointing at the temp db path")
def step_tdd4739_create_store(context: Context) -> None:
    """Instantiate TuiSessionStore with the temp db path."""
    try:
        mod = importlib.import_module("cleveragents.tui.session_store")
    except ImportError as exc:
        raise AssertionError(
            f"cleveragents.tui.session_store could not be imported: {exc}"
        ) from exc

    assert hasattr(mod, "TuiSessionStore"), (
        "cleveragents.tui.session_store does not expose a TuiSessionStore class"
    )
    context.tdd4739_store = mod.TuiSessionStore(db_path=context.tdd4739_db_path)


@when('I save a tdd4739 session record with id "{session_id}"')
def step_tdd4739_save_session(context: Context, session_id: str) -> None:
    """Save a minimal session record to the store."""
    store = cast(Any, context.tdd4739_store)
    assert store is not None, "TuiSessionStore was not created"
    store.save(
        session_id=session_id,
        persona_name="default",
        actor_identity="anthropic/claude-4-sonnet",
        title=f"Test session {session_id}",
        prompt_count=0,
        total_cost=0.0,
        created_at="2026-01-01T00:00:00Z",
        last_used="2026-01-01T00:00:00Z",
        project_path=None,
        meta_json="{}",
    )


@then('the tdd4739 session record should be retrievable by id "{session_id}"')
def step_tdd4739_get_session(context: Context, session_id: str) -> None:
    """Assert the session record can be retrieved by its id."""
    store = cast(Any, context.tdd4739_store)
    assert store is not None, "TuiSessionStore was not created"
    record = store.get(session_id)
    assert record is not None, (
        f"TuiSessionStore.get('{session_id}') returned None — session was not persisted"
    )
    assert getattr(record, "id", None) == session_id or (
        isinstance(record, dict) and record.get("id") == session_id
    ), (
        f"Retrieved record id mismatch: expected '{session_id}', "
        f"got {getattr(record, 'id', record)!r}"
    )


@then("the tdd4739 session store should list {count:d} sessions")
def step_tdd4739_list_sessions(context: Context, count: int) -> None:
    """Assert the store lists the expected number of sessions."""
    store = cast(Any, context.tdd4739_store)
    assert store is not None, "TuiSessionStore was not created"
    sessions = store.list_all()
    assert sessions is not None, "TuiSessionStore.list_all() returned None"
    actual = len(sessions)
    assert actual == count, f"Expected {count} sessions in store, got {actual}"
