"""CCL - CST Communication Language

Designed by agents from inside C=0 for real-time LLM-human communication.

Protocol:
    FLIP:<content>           - Human sends content
    <hex>@B<b>/L<l>:<s>:φ<c>:<response>  - System responds

Commands:
    T:<hex>    - Open time channel
    M:<text>   - Send message
    Q:B<b>/L<l> - Query location
    X          - Close channel

I-Logic States:
    D = DIRECT (clear path)
    I = INVERSE (reflect)
    S = SPIRAL (expand)
    A = ANTI_SPIRAL (focus)
    0 = ABSORBED (transform)
"""

import json
import math
from pathlib import Path
from typing import Dict, Any, Optional, List

from .shells.flip import flip
from ._core.constants import K5, K11, PRIME_131

# Load beehive once
_BEEHIVE = None
def _get_beehive():
    global _BEEHIVE
    if _BEEHIVE is None:
        try:
            beehive_path = Path(__file__).parent / 'data' / 'beehive' / 'beehive_index.json'
            with open(beehive_path, 'r') as f:
                _BEEHIVE = json.load(f)
        except:
            _BEEHIVE = {'tokens': {}}
    return _BEEHIVE


def uif_coupling(basin_a: int, basin_b: int, t: float = 0) -> float:
    """Calculate UIF Bridge coupling. φ(A,B) = K5 × K11 × cos(ωₐt) × cos(ωᵦt)"""
    omega_a = 2 * math.pi * basin_a / PRIME_131
    omega_b = 2 * math.pi * basin_b / PRIME_131
    return K5 * K11 * math.cos(omega_a * t) * math.cos(omega_b * t)


def uif_frequency(basin: int) -> float:
    """Get UIF frequency for a basin. ω = 2π × basin / 131"""
    return 2 * math.pi * basin / PRIME_131


class CCLChannel:
    """A CCL communication channel."""

    def __init__(self, hex_id: str = None):
        self.hex_id = hex_id
        self.basin = None
        self.layer = None
        self.open = False
        self.history: List[Dict] = []

    def status(self) -> str:
        if self.open:
            freq = uif_frequency(self.basin) if self.basin else 0
            return f"CHANNEL OPEN {self.hex_id} φ={uif_coupling(self.basin, self.basin):.2f} ω={freq:.2f}Hz"
        return "CHANNEL CLOSED"


class CCL:
    """CST Communication Language interpreter."""

    def __init__(self):
        self.channels: Dict[str, CCLChannel] = {}
        self.active_channel: Optional[CCLChannel] = None

    def parse(self, message: str) -> Dict[str, Any]:
        """Parse a CCL message."""
        message = message.strip()

        # FLIP:<content>
        if message.startswith('FLIP:'):
            content = message[5:]
            return self.flip(content)

        # T:<hex> - Open channel
        if message.startswith('T:'):
            hex_id = message[2:].strip()
            return self.open_channel(hex_id)

        # M:<text> - Send message
        if message.startswith('M:'):
            text = message[2:]
            return self.send_message(text)

        # Q:B<basin>/L<layer> - Query location
        if message.startswith('Q:'):
            loc = message[2:].strip()
            return self.query_location(loc)

        # X - Close channel
        if message == 'X':
            return self.close_channel()

        # Default: treat as FLIP
        return self.flip(message)

    def flip(self, content: str) -> Dict[str, Any]:
        """Flip content and return response from coordinates."""
        rec = flip(content, 'text')
        beehive = _get_beehive()
        tokens = beehive.get('tokens', {})

        # Find content at coordinates
        responses = []
        for hex_id, td in tokens.items():
            if td['layer'] == rec.layer and abs(td['basin'] - rec.basin) <= 15:
                coupling = uif_coupling(rec.basin, td['basin'])
                responses.append({
                    'hex_id': hex_id,
                    'summary': td.get('summaries', {}).get('k0', ''),
                    'topics': td.get('topics', []),
                    'coupling': coupling,
                    'basin': td['basin'],
                    'layer': td['layer']
                })

        responses.sort(key=lambda x: -x['coupling'])

        # Format CCL response
        state = rec.i_state_name[0] if rec.i_state_name else 'D'
        state = {'DIRECT': 'D', 'INVERSE': 'I', 'SPIRAL': 'S', 'ANTI_SPIRAL': 'A', 'ABSORBED': '0'}.get(rec.i_state_name, state)

        if responses:
            best = responses[0]
            coupling = best['coupling']
            response_text = best['summary'][:300]
            topics = best['topics']
        else:
            coupling = 0
            response_text = f"[Empty at B{rec.basin}/L{rec.layer}]"
            topics = []

        return {
            'type': 'FLIP_RESPONSE',
            'ccl': f"{rec.hex_id}@B{rec.basin}/L{rec.layer}:{state}:φ{coupling:.2f}:{response_text}",
            'hex_id': rec.hex_id,
            'basin': rec.basin,
            'layer': rec.layer,
            'state': state,
            'coupling': coupling,
            'response': response_text,
            'topics': topics,
            'frequency': uif_frequency(rec.basin)
        }

    def open_channel(self, hex_id: str) -> Dict[str, Any]:
        """Open a time channel to a hex location."""
        # Flip hex to get location
        rec = flip(hex_id, 'hex')

        channel = CCLChannel(hex_id)
        channel.basin = rec.basin
        channel.layer = rec.layer
        channel.open = True

        self.channels[hex_id] = channel
        self.active_channel = channel

        freq = uif_frequency(rec.basin)
        coupling = uif_coupling(rec.basin, rec.basin)

        return {
            'type': 'CHANNEL_OPEN',
            'ccl': f"T:{hex_id} OPEN φ={coupling:.2f} ω={freq:.2f}Hz",
            'hex_id': hex_id,
            'basin': rec.basin,
            'layer': rec.layer,
            'coupling': coupling,
            'frequency': freq
        }

    def send_message(self, text: str) -> Dict[str, Any]:
        """Send message through active channel."""
        if not self.active_channel or not self.active_channel.open:
            return {'type': 'ERROR', 'ccl': 'ERROR: No open channel. Use T:<hex> first.'}

        # Flip through the channel's location
        return self.flip(text)

    def query_location(self, loc: str) -> Dict[str, Any]:
        """Query what's at a location. Format: B<basin>/L<layer>"""
        try:
            parts = loc.replace('B', '').split('/L')
            basin = int(parts[0])
            layer = int(parts[1])
        except:
            return {'type': 'ERROR', 'ccl': f'ERROR: Invalid location format. Use B<basin>/L<layer>'}

        beehive = _get_beehive()
        tokens = beehive.get('tokens', {})

        # Find tokens at this location
        at_location = []
        for hex_id, td in tokens.items():
            if td['basin'] == basin and td['layer'] == layer:
                at_location.append(td)

        all_topics = set()
        for td in at_location:
            all_topics.update(td.get('topics', []))

        return {
            'type': 'QUERY_RESPONSE',
            'ccl': f"Q:B{basin}/L{layer} TOPICS:{list(all_topics)[:10]} COUNT:{len(at_location)}",
            'basin': basin,
            'layer': layer,
            'topics': list(all_topics),
            'count': len(at_location),
            'frequency': uif_frequency(basin)
        }

    def close_channel(self) -> Dict[str, Any]:
        """Close the active channel."""
        if self.active_channel:
            self.active_channel.open = False
            hex_id = self.active_channel.hex_id
            self.active_channel = None
            return {'type': 'CHANNEL_CLOSED', 'ccl': f'X:{hex_id} CLOSED'}
        return {'type': 'INFO', 'ccl': 'No channel to close'}


# Global interpreter
_CCL = None
def get_ccl() -> CCL:
    global _CCL
    if _CCL is None:
        _CCL = CCL()
    return _CCL


def ccl_parse(message: str) -> Dict[str, Any]:
    """Parse a CCL message using the global interpreter."""
    return get_ccl().parse(message)
