"""I-Logic Prediction

Predict routing outcomes without execution.
"""
from __future__ import annotations

from typing import List, Dict, Tuple, Any

from .states import ILogicState
from .algebra import multiply, compose, detect_cycle


def predict_route(route: str) -> Dict[str, Any]:
    """Predict routing outcome for agent path.

    Args:
        route: Comma-separated "agent:state" pairs
               e.g., "gateway:DIRECT,firewall:INVERSE,sink:ABSORBED"

    Returns:
        Dict with prediction results
    """
    I = ILogicState

    # Parse agent:state pairs
    pairs = [p.strip() for p in route.split(",")]
    agents = []
    states = []

    for pair in pairs:
        if ":" in pair:
            agent, state_name = pair.split(":", 1)
            state = I.from_name(state_name.strip())
            if state is None:
                return {"error": f"Unknown state in '{pair}'"}
            agents.append(agent.strip())
            states.append(state)
        else:
            state = I.from_name(pair)
            if state is None:
                return {"error": f"Unknown state: {pair}"}
            agents.append(f"agent_{len(agents)+1}")
            states.append(state)

    result, steps = compose(states)
    is_cycle, cycle_desc, period = detect_cycle(states)

    # Interpret result
    interpretation = {
        I.DIRECT: "Signal passes through unchanged",
        I.INVERSE: "Signal is reflected/negated",
        I.SPIRAL: "Signal is rotated (transformed)",
        I.ANTI_SPIRAL: "Signal is counter-rotated",
        I.ABSORBED: "Signal is terminated/consumed"
    }

    return {
        "route": [{"agent": a, "state": I.name(s)} for a, s in zip(agents, states)],
        "hops": len(states),
        "steps_to_result": steps,
        "final_state": I.name(result),
        "interpretation": interpretation[result],
        "cycle_analysis": {
            "is_cycle": is_cycle,
            "description": cycle_desc,
            "period": period
        },
        "early_termination": steps < len(states),
        "complexity": f"O({len(states)})"
    }


def find_resolver(condition: str) -> Dict[str, Any]:
    """Find which agent state resolves a condition.

    Args:
        condition: I-Logic state name (e.g., "INVERSE")

    Returns:
        Dict with resolver info
    """
    I = ILogicState

    condition_state = I.from_name(condition)
    if condition_state is None:
        return {"error": f"Unknown condition: {condition}"}

    if condition_state == I.ABSORBED:
        return {
            "condition": I.name(condition_state),
            "resolver": None,
            "reason": "ABSORBED has no inverse (absorbing element)"
        }

    # Find state that when multiplied gives DIRECT
    resolvers = []
    for agent_state in I.NON_ZERO_STATES:
        result = multiply(condition_state, agent_state)
        if result == I.DIRECT:
            resolvers.append({
                "agent_state": I.name(agent_state),
                "result": "DIRECT (resolved)",
                "confidence": 1.0
            })
        elif result == I.ABSORBED:
            resolvers.append({
                "agent_state": I.name(agent_state),
                "result": "ABSORBED (terminated)",
                "confidence": 0.8
            })

    return {
        "condition": I.name(condition_state),
        "resolvers": resolvers,
        "best_match": resolvers[0] if resolvers else None
    }


def compose_path_string(states_str: str) -> Dict[str, Any]:
    """Compose a path from comma-separated state names.

    Args:
        states_str: e.g., "SPIRAL,SPIRAL,SPIRAL,SPIRAL"

    Returns:
        Composition result
    """
    I = ILogicState

    state_names = [s.strip() for s in states_str.split(",")]
    states = []
    for name in state_names:
        state = I.from_name(name)
        if state is None:
            return {"error": f"Unknown state: {name}"}
        states.append(state)

    result, steps = compose(states)

    return {
        "path": [I.name(s) for s in states],
        "path_length": len(states),
        "steps_taken": steps,
        "result": I.name(result),
        "early_termination": steps < len(states)
    }
