"""
AAlgoI — Artificial Algorithm Intelligence
===========================================

Self-adaptive algorithm selection & universal problem solving.

Quick start:
    >>> from aalgoi import solve
    >>> result = solve("sort these numbers", [3, 1, 4, 1, 5])
    >>> result["result"]
    [1, 1, 3, 4, 5]

    >>> from aalgoi import UniversalSolver
    >>> solver = UniversalSolver()
    >>> result = solver.solve(spec, data)

    >>> from aalgoi import SmartSolver
    >>> solver = SmartSolver()
    >>> result = solver.ask("Find shortest path", graph)
"""

from pipeline import UniversalSolver, Result
from core.smart_solver import SmartSolver
from core import (
    ProblemSpec,
    ProblemType,
    Objective,
    Constraint,
    Explainer,
    Explanation,
    AlgorithmMarketplace,
    AlgorithmMetadata,
    Benchmarker,
    DynamicRegistry,
)
from core.rl.reward_shaper import RewardShaper

__version__ = "1.1.0"

__all__ = [
    "UniversalSolver",
    "SmartSolver",
    "Result",
    "ProblemSpec",
    "ProblemType",
    "Objective",
    "Constraint",
    "solve",
    "solve_spec",
    "explain",
    "benchmark",
    "Explainer",
    "Explanation",
    "AlgorithmMarketplace",
    "AlgorithmMetadata",
    "Benchmarker",
    "DynamicRegistry",
    "RewardShaper",
    "__version__",
]

_VERSIONS = {"aalgoi": __version__}


def solve(question, data=None, config=None, **kwargs):
    """
    Parse a plain-English question and solve it in one step.

    Parameters
    ----------
    question : str
        Natural language question (e.g. "Sort these numbers fastest possible")
    data : any, optional
        Input data (list, dict, array, graph, etc.)
    config : dict, optional
        Configuration dictionary passed to UniversalSolver
    **kwargs
        Additional keyword arguments forwarded to SmartSolver.ask()

    Returns
    -------
    dict
        Result with keys: success, result, algorithm, time_ms, answer

    Example
    -------
    >>> from aalgoi import solve
    >>> r = solve("sort ascending", [3, 1, 2])
    >>> r["result"]
    [1, 2, 3]
    """
    cfg = {"rl_deterministic": False}
    if config:
        cfg.update(config)
    solver = SmartSolver(config=cfg)
    return solver.ask(question, data, **kwargs)


def solve_spec(spec, data=None, config=None):
    """
    Solve using a pre-built ProblemSpec object.

    Parameters
    ----------
    spec : ProblemSpec
        Structured problem specification
    data : any, optional
        Input data
    config : dict, optional
        Configuration dictionary

    Returns
    -------
    dict
        Result with keys: success, result, algorithm, time_ms
    """
    cfg = {"rl_deterministic": False}
    if config:
        cfg.update(config)
    solver = UniversalSolver(config=cfg)
    return solver.solve(spec, data)


def explain(result_or_algo, data=None):
    """
    Get a human-readable explanation for an algorithm choice.

    Parameters
    ----------
    result_or_algo : dict or str
        A result dict (from solve()) containing 'algorithm' key,
        or an algorithm name string
    data : any, optional
        Input data or detail string passed through to Explainer

    Returns
    -------
    Explanation
        Structured explanation object
    """
    exp = Explainer()
    if isinstance(result_or_algo, dict):
        algo_name = result_or_algo.get("algorithm", "unknown")
        return exp.explain(algo_name, detail=str(data) if data else None)
    return exp.explain(result_or_algo, detail=str(data) if data else None)


def benchmark(spec, data):
    """
    Run comparison benchmark: AAlgoI vs standard library.

    Parameters
    ----------
    spec : ProblemSpec
        Structured problem specification
    data : any
        Input data to benchmark on

    Returns
    -------
    dict
        Benchmark results with timing, speedup, and winner
    """
    bm = Benchmarker(solver=UniversalSolver())
    return bm.compare(spec, data)
