"""
autobee.searching — Binary and linear search algorithms.
Each returns {"result": index, "found": bool, "steps": [...], "algo": "Name"}
"""


def binary_search(arr: list, target) -> dict:
    """
    Binary Search — searches a sorted array by repeatedly halving the search space.
    Automatically sorts the input array before searching.

    Args:
        arr:    List of comparable elements.
        target: Value to search for.

    Returns:
        dict with keys: result (index or -1), found (bool), steps, algo, complexity.

    Example:
        >>> from autobee import binary_search
        >>> binary_search([1, 3, 5, 7, 9], 7)["found"]
        True
        >>> binary_search([1, 3, 5, 7, 9], 7)["result"]
        3
    """
    a = sorted(arr)
    steps = []
    lo, hi = 0, len(a) - 1

    while lo <= hi:
        mid = (lo + hi) // 2
        steps.append({
            "lo": lo, "hi": hi, "mid": mid,
            "mid_value": a[mid], "target": target,
            "arr": a[:],
        })
        if a[mid] == target:
            return {
                "result": mid, "found": True,
                "steps": steps, "algo": "Binary Search",
                "complexity": {"time": "O(log n)", "space": "O(1)"},
            }
        elif a[mid] < target:
            lo = mid + 1
        else:
            hi = mid - 1

    return {
        "result": -1, "found": False,
        "steps": steps, "algo": "Binary Search",
        "complexity": {"time": "O(log n)", "space": "O(1)"},
    }


def linear_search(arr: list, target) -> dict:
    """
    Linear Search — scans every element until the target is found.

    Args:
        arr:    List of any elements.
        target: Value to search for.

    Returns:
        dict with keys: result (index or -1), found (bool), steps, algo, complexity.

    Example:
        >>> from autobee import linear_search
        >>> linear_search(["apple", "bee", "cat"], "bee")["result"]
        1
    """
    steps = []
    for i, v in enumerate(arr):
        steps.append({"index": i, "value": v, "target": target, "arr": arr[:]})
        if v == target:
            return {
                "result": i, "found": True,
                "steps": steps, "algo": "Linear Search",
                "complexity": {"time": "O(n)", "space": "O(1)"},
            }
    return {
        "result": -1, "found": False,
        "steps": steps, "algo": "Linear Search",
        "complexity": {"time": "O(n)", "space": "O(1)"},
    }
