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

Self-adaptive algorithm selection & universal problem solving.

Quick start:
    >>> from aalgoi import sort, path, knapsack
    >>> sort([3, 1, 4, 1, 5])
    [1, 1, 3, 4, 5]
    >>> path(graph, "A", "D")
    ['A', 'B', 'D']
    >>> knapsack(items, capacity=50)
    {'selected': [...], 'value': 220}
"""

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.2.0"

# ── One-function shortcuts ─────────────────────────────────
from aalgoi.shortcuts import (
    sort,
    sort_by,
    rank,
    path,
    all_paths,
    distance,
    knapsack,
    minimize,
    maximize,
    cluster,
    classify,
    regress,
    embed,
    reduce,
    blur,
    denoise,
    edges,
    enhance,
    search,
    why,
    compare,
)


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
    -------
    Result
        Result object with attribute and dict-style access.
        Keys: result, algorithm, time_ms, success, answer

    Example
    -------
    >>> from aalgoi import solve
    >>> r = solve("sort ascending", [3, 1, 2])
    >>> r.result
    [1, 2, 3]
    >>> r.ok
    True
    """
    cfg = {"rl_deterministic": False}
    if config:
        cfg.update(config)
    solver = SmartSolver(config=cfg)
    d = solver.ask(question, data, **kwargs)
    return Result(
        result=d.get("result"),
        algorithm=d.get("algorithm", ""),
        time_ms=d.get("time_ms", 0.0),
        success=d.get("success", False),
        answer=d.get("answer", ""),
    )


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
    -------
    Result
        Result object with attribute and dict-style access
    """
    cfg = {"rl_deterministic": False}
    if config:
        cfg.update(config)
    solver = UniversalSolver(config=cfg)
    d = solver.solve(spec, data)
    return Result(
        result=d.get("result"),
        algorithm=d.get("algorithm", ""),
        time_ms=d.get("time_ms", 0.0),
        success=d.get("success", False),
    )


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

    Parameters
    ----------
    result_or_algo : Result, dict, or str
        A result (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, (Result, dict)):
        algo_name = result_or_algo.get("algorithm", "unknown") if isinstance(result_or_algo, dict) else getattr(result_or_algo, "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)


__all__ = [
    # Core
    "solve",
    "solve_spec",
    "explain",
    "benchmark",
    "SmartSolver",
    "UniversalSolver",
    "Result",
    "ProblemSpec",
    "ProblemType",
    "Objective",
    "Constraint",
    "Explainer",
    "Explanation",
    "AlgorithmMarketplace",
    "AlgorithmMetadata",
    "Benchmarker",
    "DynamicRegistry",
    "RewardShaper",
    # Shortcuts
    "sort",
    "sort_by",
    "rank",
    "path",
    "all_paths",
    "distance",
    "knapsack",
    "minimize",
    "maximize",
    "cluster",
    "classify",
    "regress",
    "embed",
    "reduce",
    "blur",
    "denoise",
    "edges",
    "enhance",
    "search",
    "why",
    "compare",
    # Version
    "__version__",
]

_VERSIONS = {"aalgoi": __version__}
