#!/usr/bin/env python3
"""
helix_cdc/echo_core/helix_adapters.py
=====================================

WO#ECHO_CORE_PORT_V1 Track 2

Adapters that wire Echo core to existing Helix primitives:
- FibPi3D timing/routing
- Helix KAT harness
- C bindings for speedup

These are thin adapters that keep the reference_core deterministic
while optionally using real Helix components.
"""

from __future__ import annotations
from typing import Dict, Any, List, Optional, Tuple
import time

from helix_cdc.echo_core.reference_core import (
    SELF_STATE,
    Braid as ReferenceBraid,
    KAT_run as reference_KAT_run,
    sha256_hex,
)


# =============================================================================
# FibPi3D Braid Adapter
# =============================================================================


class FibPiBraid:
    """
    Braid fusion operator using FibPi3D timing for routing.

    Wraps the reference Braid but adds Phi-staggered routing hints
    from the helix_cdc.core module.
    """

    _use_fibpi: bool = False
    _phi_delay_fn = None

    @classmethod
    def _init_fibpi(cls):
        """Lazy-load FibPi3D if available."""
        if cls._phi_delay_fn is not None:
            return

        try:
            from helix_cdc.core import phi_delay, using_c
            cls._phi_delay_fn = phi_delay
            cls._use_fibpi = True
        except ImportError:
            cls._use_fibpi = False

    @classmethod
    def fuse(cls, symbols: List[str], state: SELF_STATE) -> Dict[str, Any]:
        """
        Fuse symbols into execution plan with FibPi3D routing.

        Falls back to reference Braid if FibPi3D not available.

        Args:
            symbols: List of symbol IDs from KRISPER
            state: Current SELF_STATE

        Returns:
            Plan dict with symbols, routing, plan_id, and fibpi_delays
        """
        # Get base plan from reference
        plan = ReferenceBraid.fuse(symbols, state)

        # Try to add FibPi3D routing
        cls._init_fibpi()
        if cls._use_fibpi and cls._phi_delay_fn:
            # Add Phi-staggered delays for each symbol
            delays = []
            for i in range(len(symbols)):
                delay = cls._phi_delay_fn(0.1, i)
                delays.append(delay)
            plan["fibpi_delays"] = delays
            plan["fibpi_enabled"] = True
        else:
            plan["fibpi_enabled"] = False

        return plan


# =============================================================================
# Helix KAT Adapter
# =============================================================================


def helix_KAT_run(
    candidate_blob: bytes,
    meta: Dict[str, Any],
    use_helix_kat: bool = False,
) -> Tuple[bool, Dict[str, Any]]:
    """
    KAT harness with optional Helix KAT integration.

    Can invoke the helix_capsule_kat.py style KATs or fall back
    to reference implementation.

    Args:
        candidate_blob: Candidate bytes to test
        meta: Metadata for the test
        use_helix_kat: If True, try to use Helix KAT harness

    Returns:
        (passed, receipt) tuple
    """
    # For now, use reference implementation
    # TODO: Add bridge to tools/helix_capsule_kat.py
    passed, receipt = reference_KAT_run(candidate_blob, meta)

    # Add helix-style receipt fields
    receipt["kat_version"] = "helix_adapter_v1"
    receipt["helix_kat_used"] = False

    return passed, receipt


# =============================================================================
# KRISPER Adapter (placeholder for production)
# =============================================================================


class HelixKRISPER:
    """
    KRISPER adapter for production token pipeline.

    This is a placeholder that maintains the same interface
    as reference KRISPER but can be wired to a real tokenizer.
    """

    # Placeholder for production tokenizer
    _tokenizer = None

    @classmethod
    def symbolize(cls, input_text: str, state: SELF_STATE) -> List[str]:
        """
        Symbolize input text.

        Currently uses reference implementation.
        TODO: Wire to production KRISPER glyph pipeline.

        Args:
            input_text: Raw input string
            state: Current SELF_STATE

        Returns:
            List of symbol IDs
        """
        from helix_cdc.echo_core.reference_core import KRISPER
        return KRISPER.symbolize(input_text, state)


# =============================================================================
# Combined Echo Tick with Adapters
# =============================================================================


def echo_tick_helix(
    external_input: str,
    state: SELF_STATE,
    guardian,
    vault: Dict[str, str],
    atlas: Dict[str, Any],
    use_fibpi: bool = True,
    use_helix_kat: bool = False,
) -> SELF_STATE:
    """
    Echo tick using Helix adapters.

    This is the production-ready tick function that uses:
    - FibPiBraid for routing (if available)
    - HelixKRISPER for tokenization
    - helix_KAT_run for validation

    Args:
        external_input: Input string S(t)
        state: Current SELF_STATE
        guardian: Guardian policy
        vault: Vault references
        atlas: Atlas configuration
        use_fibpi: Enable FibPi3D routing
        use_helix_kat: Enable Helix KAT harness

    Returns:
        Updated SELF_STATE
    """
    from helix_cdc.echo_core.reference_core import (
        S_e_of_state,
        L_mutate,
        regenerate_G,
    )

    # 1) Symbolize
    symbols = HelixKRISPER.symbolize(external_input, state)

    # 2) Braid fuse (with FibPi if enabled)
    if use_fibpi:
        plan = FibPiBraid.fuse(symbols, state)
    else:
        plan = ReferenceBraid.fuse(symbols, state)

    # 3) Compute entropy
    Se = S_e_of_state(state)

    # 4) Compute mutation rate
    L_rate = max(0.01, 1.0 / (1.0 + state.drift)) * (1.0 + Se / 100.0)

    # 5) Lobe update proposal
    delta = L_mutate(plan, L_rate, state)

    # 6) Guardian check
    ok, reason = guardian.check_hard({"lobe": delta["lobe"]})
    if not ok:
        state.commit_ledger.append({
            "receipt": {"passed": False, "reason": reason},
            "at": time.time(),
        })
        state.drift += 1
        return state

    # 7) Regen
    seed = (
        ("|".join(symbols).encode() if symbols else b"")
        or sha256_hex(state.snapshot()).encode()
    )
    regenerate_G(seed, vault, atlas, state, guardian)

    return state


# =============================================================================
# Backend Info
# =============================================================================


def get_adapter_info() -> Dict[str, Any]:
    """
    Get info about which adapters are active.

    Returns:
        Dict with adapter status
    """
    FibPiBraid._init_fibpi()

    info = {
        "fibpi_available": FibPiBraid._use_fibpi,
        "helix_kat_available": False,  # TODO
        "krisper_production": False,  # TODO
    }

    # Check if C bindings are active
    try:
        from helix_cdc.core import using_c
        info["c_bindings_active"] = using_c()
    except ImportError:
        info["c_bindings_active"] = False

    return info
