# ═══════════════════════════════════════════════════════════════════════════════
# d10z/tta/filaments.py
# TTA FILAMENTS - FREQUENCY AND VIBRATION CARRIERS
# ═══════════════════════════════════════════════════════════════════════════════
"""
TTA Filaments

The TTA network consists of filament pairs:
- Frequency filament (f): Carries frequency information
- Vibration filament (v): Carries vibration information

These filaments:
- Have thickness = 0.0000001% of GM·10⁻⁵¹
- Are separated by 0.0000000000001%
- Alternate: one f, one v, one f, one v...
- Contain Neusars in their central cánula

The interaction f × v generates ENERGY, which then produces INFIFOTÓNS.
"""

import numpy as np
from dataclasses import dataclass, field
from typing import List, Optional, Tuple
from ..core.constants import (
    FILAMENT_THICKNESS, FILAMENT_SEPARATION,
    GM_SCALE, EPSILON_IFI
)


@dataclass
class Filament:
    """
    Base class for TTA filaments.
    
    Attributes
    ----------
    intensity : float
        Current intensity of the filament
    phase : float
        Phase of oscillation
    position : np.ndarray
        Position of filament endpoint
    filament_type : str
        'frequency' or 'vibration'
    """
    intensity: float = 1.0
    phase: float = 0.0
    position: np.ndarray = field(default_factory=lambda: np.zeros(3))
    filament_type: str = "base"
    
    @property
    def thickness(self) -> float:
        """Physical thickness of filament"""
        return FILAMENT_THICKNESS
    
    def oscillate(self, dt: float, omega: float = 1.0):
        """Advance filament phase"""
        self.phase = (self.phase + omega * dt) % (2 * np.pi)
    
    def current_value(self) -> float:
        """Current oscillation value"""
        return self.intensity * np.sin(self.phase)


@dataclass
class FrequencyFilament(Filament):
    """
    Frequency-carrying filament.
    
    Carries the frequency component of nodal dynamics.
    """
    filament_type: str = "frequency"
    base_frequency: float = 1e12  # Hz
    
    def get_frequency(self) -> float:
        """Get current frequency value f"""
        return self.base_frequency * (1 + 0.1 * self.current_value())


@dataclass  
class VibrationFilament(Filament):
    """
    Vibration-carrying filament.
    
    Carries the vibration component of nodal dynamics.
    """
    filament_type: str = "vibration"
    base_amplitude: float = 1.0
    
    def get_vibration(self) -> float:
        """Get current vibration value v"""
        return self.base_amplitude * abs(self.current_value())


@dataclass
class FilamentPair:
    """
    A pair of frequency and vibration filaments.
    
    These pairs are the fundamental units of TTA structure.
    Energy is generated by their interaction.
    
    Attributes
    ----------
    f_filament : FrequencyFilament
        The frequency filament
    v_filament : VibrationFilament
        The vibration filament
    """
    f_filament: FrequencyFilament
    v_filament: VibrationFilament
    
    @property
    def separation(self) -> float:
        """Physical separation between filaments"""
        return FILAMENT_SEPARATION
    
    def compute_energy(self, kappa_E: float = 1.0) -> float:
        """
        Compute energy generated by f×v interaction.
        
        E = κ_E × f × v
        
        This is the fundamental energy generation mechanism.
        """
        f = self.f_filament.get_frequency()
        v = self.v_filament.get_vibration()
        return kappa_E * f * v
    
    def compute_infifotons(self, kappa_E: float = 1.0) -> int:
        """
        Compute number of infifotóns generated.
        
        N_ifi = E / ε_ifi
        """
        E = self.compute_energy(kappa_E)
        return int(E / EPSILON_IFI)
    
    def evolve(self, dt: float, omega_f: float = 1.0, omega_v: float = 1.1):
        """
        Evolve both filaments in time.
        
        The slight frequency difference (omega_f ≠ omega_v) creates
        beating patterns that generate structure.
        """
        self.f_filament.oscillate(dt, omega_f)
        self.v_filament.oscillate(dt, omega_v)


def create_filament_network(n_pairs: int = 19,
                           arrangement: str = 'flower',
                           seed: Optional[int] = None) -> List[FilamentPair]:
    """
    Create a network of filament pairs.
    
    Parameters
    ----------
    n_pairs : int
        Number of filament pairs
    arrangement : str
        Spatial arrangement ('flower', 'linear', 'random')
    seed : int, optional
        Random seed
    
    Returns
    -------
    List[FilamentPair]
        List of filament pairs forming the network
    """
    rng = np.random.default_rng(seed)
    pairs = []
    
    for i in range(n_pairs):
        # Random initial phases
        phase_f = rng.uniform(0, 2*np.pi)
        phase_v = rng.uniform(0, 2*np.pi)
        
        # Position based on arrangement
        if arrangement == 'flower':
            if i == 0:
                pos = np.zeros(3)
            elif i <= 6:
                angle = (i-1) * np.pi / 3
                pos = np.array([np.cos(angle), np.sin(angle), 0])
            else:
                angle = (i-7) * np.pi / 6
                pos = 2 * np.array([np.cos(angle), np.sin(angle), 0])
        elif arrangement == 'linear':
            pos = np.array([i, 0, 0])
        else:  # random
            pos = rng.normal(0, 1, 3)
        
        f_fil = FrequencyFilament(
            intensity=rng.uniform(0.8, 1.2),
            phase=phase_f,
            position=pos.copy()
        )
        
        v_fil = VibrationFilament(
            intensity=rng.uniform(0.8, 1.2),
            phase=phase_v,
            position=pos + np.array([0, 0, FILAMENT_SEPARATION])
        )
        
        pairs.append(FilamentPair(f_fil, v_fil))
    
    return pairs


def total_network_energy(pairs: List[FilamentPair], 
                         kappa_E: float = 1.0) -> float:
    """Compute total energy generated by filament network"""
    return sum(pair.compute_energy(kappa_E) for pair in pairs)


def total_infifotons(pairs: List[FilamentPair], 
                    kappa_E: float = 1.0) -> int:
    """Compute total infifotóns generated by network"""
    return sum(pair.compute_infifotons(kappa_E) for pair in pairs)


__all__ = [
    'Filament', 'FrequencyFilament', 'VibrationFilament',
    'FilamentPair', 'create_filament_network',
    'total_network_energy', 'total_infifotons'
]
