"""bandito assert — run assertion functions against traces."""

from __future__ import annotations

import os
import sys

from . import get_client


def run_assert(
    project: str,
    file_path: str,
    *,
    last: int | None = None,
    store: bool = False,
) -> None:
    import importlib.util
    import inspect

    from .assertions_impl import assert_traces
    from ..storage import get_store

    # Load assertion functions from file
    if not os.path.exists(file_path):
        print(f"\n  File not found: {file_path}\n")
        sys.exit(1)

    spec = importlib.util.spec_from_file_location("_user_assertions", file_path)
    if spec is None or spec.loader is None:
        print(f"\n  Could not load: {file_path}\n")
        sys.exit(1)

    module = importlib.util.module_from_spec(spec)
    try:
        spec.loader.exec_module(module)
    except Exception as e:
        print(f"\n  Error loading {file_path}: {e}\n")
        sys.exit(1)

    # Discover assertion functions: callable, not private, not class
    assertions = []
    for name, obj in inspect.getmembers(module):
        if name.startswith("_"):
            continue
        if callable(obj) and not inspect.isclass(obj):
            assertions.append(obj)

    if not assertions:
        print(f"\n  No assertion functions found in {file_path}.")
        print("  Define functions like: def my_check(trace): return bool(...)\n")
        sys.exit(1)

    # Load traces and run
    trace_store = get_store(project=project)
    result = assert_traces(
        project,
        assertions,
        last=last,
        store=trace_store,
    )

    if result.total_traces == 0:
        print(f"\n  No traces found for '{project}'.\n")
        sys.exit(1)

    print(result.summary())

    # Store results if requested
    if store:
        client = get_client()
        if client:
            client.write_assertion_run(project, result.to_dict())
            print(f"  Results stored on backend.\n")

    sys.exit(0 if result.all_passed else 1)
