"""L9 MEMBRANE Layer

Information flow and transmission.
"""
from __future__ import annotations

from typing import List, Optional

from .base import Layer, LayerID, Token
from .._core import PRIME_131, PHI


class L9_Membrane(Layer):
    """L9 MEMBRANE: Information flow and transmission."""

    LAYER_ID = LayerID.MEMBRANE
    LAYER_NAME = "MEMBRANE"
    LAYER_DESCRIPTION = "Information flow and transmission"

    def query(self, pattern: str, limit: int = 100) -> List[Token]:
        """Query by membrane pattern."""
        pattern = pattern.lower()

        if pattern == "permeable":
            # High coherence = permeable
            return sorted(self._memory._tokens.values(),
                         key=lambda t: t.coherence, reverse=True)[:limit]
        elif pattern == "impermeable":
            # Low coherence = impermeable
            return sorted(self._memory._tokens.values(),
                         key=lambda t: t.coherence)[:limit]
        elif pattern == "boundary":
            # Tokens at basin boundaries (near layer transitions)
            boundary_basins = {14, 29, 43, 58, 72, 87, 101, 116}
            return [t for t in self._memory._tokens.values()
                    if t.basin in boundary_basins][:limit]

        return list(self._memory._tokens.values())[:limit]

    def filter(self, tokens: List[Token], **criteria) -> List[Token]:
        """Filter by membrane criteria."""
        results = tokens

        if "permeability" in criteria:
            perm = criteria["permeability"]
            if perm == "high":
                results = [t for t in results if t.coherence >= 0.8]
            elif perm == "low":
                results = [t for t in results if t.coherence < 0.5]

        if "min_coherence" in criteria:
            min_c = criteria["min_coherence"]
            results = [t for t in results if t.coherence >= min_c]

        return results

    def navigate(self, token: Token, direction: str) -> Optional[Token]:
        """Navigate through membrane."""
        if direction == "through":
            # Cross to reflected basin
            reflected_basin = (PRIME_131 - 1 - token.basin) % PRIME_131
            for t in self._memory._tokens.values():
                if t.basin == reflected_basin:
                    return t
        elif direction == "heal":
            # Find token that can heal this one
            for t in self._memory._tokens.values():
                if t.coherence > token.coherence and t.basin == token.basin:
                    return t
        return None

    def distance(self, a: Token, b: Token) -> float:
        """Membrane distance: transmission cost."""
        # Cost is inverse of coherence
        avg_coherence = (a.coherence + b.coherence) / 2
        basin_diff = abs(a.basin - b.basin)
        return basin_diff / (avg_coherence + 0.01)

    def permeability(self, token: Token) -> float:
        """Get membrane permeability for token."""
        return token.coherence

    def transmission_cost(self, source: Token, target: Token) -> float:
        """Calculate cost to transmit from source to target."""
        return self.distance(source, target)

    def heal(self, token: Token) -> float:
        """Simulate healing - returns new coherence."""
        # Healing increases coherence by phi factor
        new_coherence = min(1.0, token.coherence * PHI)
        return new_coherence

    def reflect_basin(self, basin: int) -> int:
        """Get reflected basin (membrane flip pair)."""
        return (PRIME_131 - 1 - basin) % PRIME_131
