"""
SRL Integration - Self-Referential Loop Pathfinding
Standalone version for cubesquare package.

SRL Formula: t = d/t -> t^2 = d -> t = sqrt(d)
O(1) computation via Python math.isqrt.

ABSORBED Physics (Euler + Hamiltonian):
  F(z,C) = z³·e^(i·2π/131) accumulates rotation per bounce.
  Each ABSORBED crossing lands at a different face of the C=0 sphere
  because the Euler rotation 2π/131 per bounce is accumulating.
  Different angular positions → different K11 coupling strengths
  to L9 membrane → different transmission/reflection ratios.
  Energy is conserved (H = T + V) — never destroyed.
"""

import math
from typing import List, Dict, Any


# Constants
PHI = 1.618033988749895
K5 = 1.158814
K11 = 9.204026
PRIME_131 = 131
EULER_STEP = 2 * math.pi / PRIME_131  # Rotation per bounce


def srl_distance(d: int) -> int:
    """
    Compute SRL distance: t = sqrt(d)

    Args:
        d: Distance value (must be >= 0)

    Returns:
        SRL time t where t^2 = d

    Performance: O(1) via math.isqrt

    Mathematical Proof:
    Given t = d/t (self-referential definition)
    Multiply both sides by t: t^2 = d
    Take square root: t = sqrt(d)
    """
    if d <= 0:
        return 0
    if d == 1:
        return 1
    return int(math.isqrt(d))


def bounded_sqrt(d: int, min_val: int = 1, max_val: int = 10000) -> int:
    """
    Compute bounded SRL distance with min/max clamps.

    Args:
        d: Distance value
        min_val: Minimum result (default: 1)
        max_val: Maximum result (default: 10000)

    Returns:
        SRL time t clamped to [min_val, max_val]
    """
    t = int(math.isqrt(d)) if d > 0 else 0
    return max(min_val, min(t, max_val))


def srl_pathfind(from_hex: str, to_hex: str, max_depth: int = 100) -> List[str]:
    """
    Find path between hex IDs using SRL formula.

    Note: Standalone version returns simple direct path.
    Full pathfinding requires relationship graph.

    Args:
        from_hex: Starting hex ID
        to_hex: Target hex ID
        max_depth: Maximum path length

    Returns:
        List of hex IDs in path
    """
    if from_hex == to_hex:
        return [from_hex]
    return [from_hex, to_hex]


def srl_div_zero_path(hex_id: str) -> int:
    """
    Handle division-by-zero case via SRL formula.

    Args:
        hex_id: Hex ID to analyze

    Returns:
        SRL distance (0 if ABSORBED, 1 if DIRECT, sqrt(d) otherwise)
    """
    area = int(hex_id[:2], 16) if len(hex_id) >= 2 and hex_id[:2].isalnum() else 0

    if area == 0:
        return 0

    return srl_distance(area)


def srl_phi_depth(depth: int) -> float:
    """
    Compute phi-scaled depth for SRL operations.

    Args:
        depth: Tree depth level

    Returns:
        Phi-scaled depth (depth / phi)
    """
    return depth / PHI


def srl_k5_boundary(distance: int) -> int:
    """
    Apply K5 boundary stabilization to SRL distance.

    Args:
        distance: Raw SRL distance

    Returns:
        K5-bounded distance
    """
    if distance <= K5:
        return distance
    return distance % K5


def srl_morton_encode(x: int, y: int, z: int) -> int:
    """
    Encode 3D coordinates to Morton Z-order code.

    Args:
        x, y, z: 3D coordinates

    Returns:
        Morton code (interleaved bits)
    """
    def part_by_3(n):
        """Expand bits for 3D Morton encoding."""
        n &= 0x1FFFFF
        n = (n | (n << 32)) & 0x1F00000000FFFF
        n = (n | (n << 16)) & 0x1F0000FF0000FF
        n = (n | (n << 8))  & 0x100F00F00F00F00F
        n = (n | (n << 4))  & 0x10C30C30C30C30C3
        n = (n | (n << 2))  & 0x1249249249249249
        return n
    return part_by_3(x) | (part_by_3(y) << 1) | (part_by_3(z) << 2)


# =========================================================================
# ABSORBED PHYSICS: Euler Rotation + K11 Membrane Coupling
# =========================================================================

def absorbed_exit_face(bounce_count: int) -> Dict[str, Any]:
    """Predict the angular position (exit face) on the C=0 Fernandez sphere.

    Each bounce accumulates Euler rotation: θ = bounce_count × 2π/131.
    F(z,C) = z³·e^(i·2π/131) drives the traversal.
    Two tasks with different bounce counts arrive at different faces
    of the C=0 sphere → different K11 coupling → different T/R ratios.

    Args:
        bounce_count: Number of I-Logic bounces before ABSORBED crossing.

    Returns:
        Dict with angular position, K11 coupling, and T/R prediction.
    """
    theta = bounce_count * EULER_STEP
    # Normalize to [0, 2π)
    theta_norm = theta % (2 * math.pi)

    # K11 coupling strength at this angular position
    # φ(A,B) = K5 × K11 × cos(ωₐt) × cos(ωᵦt)
    # At the membrane: ω depends on angular position
    cos_theta = math.cos(theta_norm)
    coupling = K5 * K11 * cos_theta * cos_theta

    # Transmission/reflection ratio via K11 QRS
    # High coupling → more transmission through L9 → L10-L12
    # Low coupling → more reflection back to L1-L9
    # When cos(θ) ≈ 0 (at L4-L5 region), coupling weakens → natural load balancing
    transmission = abs(cos_theta)
    reflection = 1.0 - transmission

    # Which face of the C=0 sphere (modular position)
    face_index = bounce_count % PRIME_131

    # Basin on L9 membrane (basins 117-130)
    membrane_basin = 117 + (face_index % 14)

    return {
        "bounce_count": bounce_count,
        "theta": theta_norm,
        "theta_degrees": math.degrees(theta_norm),
        "face_index": face_index,
        "cos_theta": cos_theta,
        "k11_coupling": coupling,
        "transmission_ratio": transmission,
        "reflection_ratio": reflection,
        "membrane_basin": membrane_basin,
        "exit_prediction": "TRANSMIT_L10" if transmission > 0.5 else "REFLECT_L1_L9",
        "energy_conserved": True,  # H = T + V always
    }


def membrane_load_balance(basin_id: int) -> Dict[str, Any]:
    """Compute L9 membrane self-regulating load balance for a basin.

    Under high load, cos(ω) approaching 0 at L4-L5 means K11 coupling
    weakens → more reflection back to L1-L9 → system absorbs its own
    overload by routing internally. Natural pressure valve built into
    Hamiltonian conservation.

    Args:
        basin_id: Basin ID (0-130).

    Returns:
        Dict with coupling strength and load balance prediction.
    """
    # Basin frequency: ω = 2π × basin/131
    omega = 2 * math.pi * basin_id / PRIME_131
    cos_omega = math.cos(omega)

    # K11 coupling at this basin's frequency
    coupling = K5 * K11 * cos_omega * cos_omega

    # Layer for this basin
    layer = basin_id // 15 + 1 if basin_id < 131 else 10

    # Natural load balance: L4-L5 (basins 44-72) have cos → 0
    # This means coupling weakens → more reflection → self-regulation
    is_pressure_zone = 44 <= basin_id <= 72
    overload_safe = coupling < (K5 * K11 * 0.25)  # < 25% coupling = high reflection

    return {
        "basin_id": basin_id,
        "layer": layer,
        "omega": omega,
        "cos_omega": cos_omega,
        "k11_coupling": coupling,
        "max_coupling": K5 * K11,
        "coupling_ratio": coupling / (K5 * K11) if K5 * K11 > 0 else 0,
        "is_pressure_zone": is_pressure_zone,
        "overload_safe": overload_safe,
        "transmission_ratio": abs(cos_omega),
        "reflection_ratio": 1.0 - abs(cos_omega),
        "load_balance": "SELF_REGULATING" if is_pressure_zone else "NORMAL",
    }
