#!/usr/bin/env python3
"""
نموذج عددي مستقر للعاصفة الثلجية
مع عوامل تخميد ومقاييس واقعية
"""

import numpy as np
from dataclasses import dataclass
from typing import Dict, List
import time

print("="*80)
print("🌨️  نموذج العاصفة الثلجية المستقر والواقعي")
print("Snow Dust Project - نسخة مصححة ومعادلات مستقرة")
print("="*80)

# ============================================
# هياكل البيانات الدقيقة
# ============================================
@dataclass
class TimeStep:
    """حالة النظام في خطوة زمنية واحدة"""
    t: float                    # الزمن [s]
    rho_p: float               # كثافة الجسيمات [particles/m³]
    v_p: np.ndarray           # سرعة الجسيمات [m/s]
    v_wind: np.ndarray        # سرعة الرياح [m/s]
    E_field: np.ndarray       # المجال الكهربائي [V/m]
    delta_T: float            # فرق الحرارة [K]
    d_p: float                # قطر الجسيم [m]
    q_p: float                # شحنة الجسيم [C]
    position: np.ndarray      # الموقع [m]
    visibility: float         # الرؤية [m]
    signal_strength: float    # قوة إشارة الملاحة [0-1]
    nav_viable: bool          # هل الملاحة ممكنة؟

# ============================================
# فئة النموذج المستقر
# ============================================
class StableSnowstormSolver:
    """
    نموذج مستقر مع عوامل تخميد ومقاييس واقعية
    """
    
    def __init__(self):
        # الثوابت الفيزيائية الدقيقة
        self.g = np.array([0.0, 0.0, -9.80665])      # تسارع الجاذبية [m/s²]
        self.epsilon0 = 8.854187817e-12              # سماحية الفراغ [F/m]
        self.eta_air = 1.72e-5                       # لزوجة الهواء [Pa·s]
        self.alpha_air = 1.9e-5                      # نفوذية حرارية [m²/s]
        self.rho_ice = 917                           # كثافة الجليد [kg/m³]
        
        # شروط الابتدائية REALISTIC
        self.initial_state = TimeStep(
            t=0.0,
            rho_p=1.0e6,                             # مليون جسيم/م³ (عاصفة متوسطة)
            v_p=np.array([0.0, 0.0, -0.5]),          # سقوط أبطأ
            v_wind=np.array([8.0, 0.0, 0.0]),        # رياح معتدلة
            E_field=np.array([0.0, 0.0, 0.0]),
            delta_T=5.0,
            d_p=200e-6,
            q_p=1.0e-15,                             # 1 فمتوكولوم (أقل بـ 50×)
            position=np.array([0.0, 0.0, 1000.0]),
            visibility=0.0,
            signal_strength=0.0,
            nav_viable=False
        )
        
        # معاملات النموذج المصححة
        self.sigma_ext = 2.0 * np.pi * (200e-6)**2   # مقطع أكبر (واقعي)
        self.S_p = 1.0e5                             # معدل سقوط أقل
        self.L_p = 0.2                               # ترسيب أسرع
        self.R0 = 10000.0                            # رؤية قصوى
        self.E_max = 20000.0                         # أقصى مجال واقعي
        self.R_max = 500.0                           # أقصى رؤية مفيدة واقعية
        self.R_cloud = 100.0                         # نصف قطر سحابة أصغر
        
        # عوامل التخميد للاستقرار
        self.damping_position = 0.001                # تخميد المواقع
        self.damping_velocity = 0.01                 # تخميد السرعات
        self.max_step = 0.1                          # أقصى خطوة زمنية [s]
    
    def stable_visibility(self, rho_p: float) -> float:
        """رؤية واقعية مع حدود معقولة"""
        tau = self.sigma_ext * rho_p
        
        # في العواصف الثلجية الشديدة، الرؤية 10-50 متر
        if tau > 20:
            return 10.0  # عاصفة شديدة
        elif tau > 5:
            return 50.0  # عاصفة متوسطة
        elif tau > 1:
            return 200.0  # ضباب خفيف
        else:
            return min(self.R0 * np.exp(-tau), 1000.0)  # حد أقصى 1 كم
    
    def stable_electric_field(self, rho_p: float, q_p: float) -> np.ndarray:
        """مجال كهربائي واقعي مع حدود فيزيائية"""
        rho_e = rho_p * q_p
        
        # قانون غاوس مع حدود واقعية
        E_z = (rho_e * self.R_cloud) / (3.0 * self.epsilon0)
        
        # حدود فيزيائية (لا يتجاوز 50 كيلو فولت/متر)
        E_z = min(E_z, 50000.0)
        E_z = max(E_z, 0.0)
        
        # تقلبات واقعية صغيرة
        E_x = 0.1 * E_z * np.random.randn()
        E_y = 0.1 * E_z * np.random.randn()
        
        # تطبيع للحدود الواقعية
        E_mag = np.sqrt(E_x**2 + E_y**2 + E_z**2)
        if E_mag > 50000:
            scale = 50000 / E_mag
            E_x *= scale
            E_y *= scale
            E_z *= scale
        
        return np.array([E_x, E_y, E_z])
    
    def system_rates_stable(self, state: TimeStep) -> Dict:
        """معدلات مستقرة مع عوامل تخميد"""
        # 1. كثافة الجسيمات (مع تخميد)
        divergence = 0.05 * state.rho_p * state.v_wind[0]
        drho_dt = -divergence + self.S_p - self.L_p * state.rho_p
        drho_dt *= 0.5  # تخميد
        
        # 2. سرعة الجسيمات (مع تخميد قوي)
        r_p = state.d_p / 2.0
        m_p = (4.0/3.0) * np.pi * r_p**3 * self.rho_ice
        
        # مقاومة هواء أقوى (Stokes law)
        drag_coeff = (6.0 * np.pi * self.eta_air * r_p) / m_p
        drag_coeff *= 2.0  # مقاومة أكبر للاستقرار
        
        dv_dt = (self.g - drag_coeff * (state.v_p - state.v_wind) + 
                (state.q_p / m_p) * state.E_field)
        
        # تخميد السرعة
        dv_dt -= self.damping_velocity * state.v_p
        
        # 3. فرق الحرارة (مستقر)
        convection = 0.005 * np.linalg.norm(state.v_wind) * state.delta_T
        diffusion = -self.alpha_air * state.delta_T / 50.0
        ddeltaT_dt = -convection + diffusion
        
        # 4. مجال كهربائي مستقر
        E_field_new = self.stable_electric_field(state.rho_p, state.q_p)
        
        # 5. رؤية واقعية
        visibility = self.stable_visibility(state.rho_p)
        
        # 6. قوة إشارة واقعية
        E_mag = np.linalg.norm(state.E_field)
        signal = (E_mag / self.E_max) * (visibility / self.R_max)
        signal = max(0.0, min(1.0, signal))
        
        return {
            'drho_dt': drho_dt,
            'dv_dt': dv_dt,
            'ddeltaT_dt': ddeltaT_dt,
            'E_field': E_field_new,
            'visibility': visibility,
            'signal_strength': signal,
            'nav_viable': signal > 0.2  # عتبة أقل للواقعية
        }
    
    def euler_step_stable(self, state: TimeStep, dt: float) -> TimeStep:
        """خطوة أويلر مستقرة (بسيطة لكن مستقرة)"""
        rates = self.system_rates_stable(state)
        
        # تحديث مع تخميد
        dt_eff = min(dt, self.max_step)  # خطوة زمنية محدودة
        
        # تحديث الكثافة
        rho_p_new = state.rho_p + dt_eff * rates['drho_dt']
        rho_p_new = max(rho_p_new, 1e4)   # حد أدنى
        rho_p_new = min(rho_p_new, 5e6)   # حد أقصى (عاصفة شديدة)
        
        # تحديث السرعة مع تخميد
        v_p_new = state.v_p + dt_eff * rates['dv_dt']
        v_p_mag = np.linalg.norm(v_p_new)
        if v_p_mag > 10:  # حد أقصى للسرعة
            v_p_new = v_p_new * (10 / v_p_mag)
        
        # تحديث الحرارة
        delta_T_new = state.delta_T + dt_eff * rates['ddeltaT_dt']
        delta_T_new = max(delta_T_new, 0.1)
        delta_T_new = min(delta_T_new, 20.0)
        
        # تحديث الموقع مع تخميد
        position_new = state.position + dt_eff * state.v_p
        position_new *= (1 - self.damping_position)  # تخميد المواقع
        
        # تقييد الموقع ضمن نطاق واقعي (±10 كم)
        for i in range(3):
            if abs(position_new[i]) > 10000:
                position_new[i] = np.sign(position_new[i]) * 10000
        
        # تحديث المجال الكهربائي
        E_field_new = rates['E_field']
        
        # تحديث الشحنة (تقلبات صغيرة)
        q_p_new = state.q_p * np.random.uniform(0.95, 1.05)
        q_p_new = max(q_p_new, 1e-16)  # حد أدنى
        q_p_new = min(q_p_new, 1e-13)  # حد أقصى
        
        # تحديث الرياح (تقلبات واقعية)
        if np.random.random() < 0.2:
            wind_change = np.array([
                np.random.uniform(-2, 2),
                np.random.uniform(-1, 1),
                0.0
            ])
            v_wind_new = state.v_wind + wind_change
        else:
            v_wind_new = state.v_wind.copy()
        
        # تقييد سرعة الرياح
        wind_mag = np.linalg.norm(v_wind_new)
        if wind_mag > 30:  # حد أقصى للرياح
            v_wind_new = v_wind_new * (30 / wind_mag)
        
        # إنشاء الحالة الجديدة
        new_state = TimeStep(
            t=state.t + dt_eff,
            rho_p=rho_p_new,
            v_p=v_p_new,
            v_wind=v_wind_new,
            E_field=E_field_new,
            delta_T=delta_T_new,
            d_p=state.d_p,
            q_p=q_p_new,
            position=position_new,
            visibility=rates['visibility'],
            signal_strength=rates['signal_strength'],
            nav_viable=rates['nav_viable']
        )
        
        return new_state
    
    def solve_stable(self, t_end: float = 120.0, dt: float = 0.05) -> List[TimeStep]:
        """حل مستقر مع مراقبة"""
        print(f"\n🌨️  بدء محاكاة عاصفة ثلجية واقعية")
        print(f"   المدة: {t_end} ثانية")
        print(f"   خطوة زمنية: {dt} ثانية")
        print("-"*60)
        
        states = []
        current_state = self.initial_state
        
        # حساب المعدلات الابتدائية
        initial_rates = self.system_rates_stable(current_state)
        current_state.visibility = initial_rates['visibility']
        current_state.signal_strength = initial_rates['signal_strength']
        current_state.nav_viable = initial_rates['nav_viable']
        
        states.append(current_state)
        
        n_steps = int(t_end / dt)
        
        for step in range(1, n_steps + 1):
            current_state = self.euler_step_stable(current_state, dt)
            states.append(current_state)
            
            # عرض التقدم
            if step % 400 == 0:  # كل 20 ثانية
                E_mag = np.linalg.norm(current_state.E_field)
                print(f"   ⏱️  t = {current_state.t:5.1f}s | كثافة = {current_state.rho_p/1e6:4.2f}M/m³ | "
                      f"رؤية = {current_state.visibility:5.1f}m | مجال = {E_mag:6.1f}V/m | "
                      f"إشارة = {current_state.signal_strength:.3f}")
        
        print("-"*60)
        print("✅ اكتملت المحاكاة المستقرة!")
        
        return states

# ============================================
# التنفيذ الرئيسي
# ============================================
def main():
    """الدالة الرئيسية"""
    solver = StableSnowstormSolver()
    
    # محاكاة عاصفة واقعية (دقيقتان)
    start_time = time.time()
    states = solver.solve_stable(t_end=120.0, dt=0.05)
    end_time = time.time()
    
    print(f"\n⏱️  وقت التنفيذ: {end_time - start_time:.2f} ثانية")
    
    # تحليل النتائج
    print("\n📊 تحليل النتائج الواقعية:")
    print("="*60)
    
    # استخراج البيانات
    times = [s.t for s in states]
    densities = [s.rho_p for s in states]
    visibilities = [s.visibility for s in states]
    e_fields = [np.linalg.norm(s.E_field) for s in states]
    signals = [s.signal_strength for s in states]
    nav_viable = [s.nav_viable for s in states]
    
    # الإحصائيات
    nav_percentage = sum(nav_viable) / len(nav_viable) * 100
    
    print(f"   متوسط كثافة الجسيمات: {np.mean(densities)/1e6:.2f} مليون/م³")
    print(f"   نطاق الكثافة: [{np.min(densities)/1e6:.2f}, {np.max(densities)/1e6:.2f}] مليون/م³")
    print(f"   متوسط الرؤية: {np.mean(visibilities):.1f} متر")
    print(f"   نطاق الرؤية: [{np.min(visibilities):.1f}, {np.max(visibilities):.1f}] متر")
    print(f"   متوسط المجال الكهربائي: {np.mean(e_fields):.1f} فولت/متر")
    print(f"   نطاق المجال: [{np.min(e_fields):.1f}, {np.max(e_fields):.1f}] فولت/متر")
    print(f"   متوسط قوة الإشارة: {np.mean(signals):.3f}")
    print(f"   نسبة الوقت المناسب للملاحة: {nav_percentage:.1f}%")
    
    # تقييم واقعي
    if nav_percentage > 60:
        print(f"\n🎯 نظام Snow Dust: ✅ فعال في هذه العاصفة")
        print("   يمكن الاعتماد عليه للملاحة")
    elif nav_percentage > 30:
        print(f"\n🎯 نظام Snow Dust: ⚠️  محدود الفعالية")
        print("   يحتاج إلى دعم GPS في بعض الأحيان")
    else:
        print(f"\n🎯 نظام Snow Dust: ❌ غير فعال")
        print("   العاصفة شديدة جداً أو الإشارة ضعيفة")
    
    print("="*60)
    
    # عرض عينة من البيانات
    print("\n📋 عينة من البيانات (كل 30 ثانية):")
    print("-"*80)
    print(f"{'الزمن':>8} {'الكثافة':>10} {'الرؤية':>10} {'E-field':>12} {'الإشارة':>8} {'ملاحة':>8}")
    print(f"{'(s)':>8} {'(M/m³)':>10} {'(m)':>10} {'(V/m)':>12} {'':>8} {'':>8}")
    print("-"*80)
    
    for i, state in enumerate(states):
        if i % 600 == 0:  # كل 30 ثانية
            E_mag = np.linalg.norm(state.E_field)
            print(f"{state.t:8.1f} {state.rho_p/1e6:10.2f} {state.visibility:10.1f} "
                  f"{E_mag:12.1f} {state.signal_strength:8.3f} "
                  f"{'✅' if state.nav_viable else '❌':>8}")
    
    print("-"*80)
    
    # الحالة النهائية
    final_state = states[-1]
    print(f"\n🎯 الحالة النهائية عند t = {final_state.t:.1f} ثانية:")
    print(f"   الموقع: [{final_state.position[0]:.1f}, {final_state.position[1]:.1f}, {final_state.position[2]:.1f}] متر")
    print(f"   سرعة الرياح: [{final_state.v_wind[0]:.1f}, {final_state.v_wind[1]:.1f}, {final_state.v_wind[2]:.1f}] م/ث")
    print(f"   شحنة الجسيم: {final_state.q_p:.2e} كولوم")
    print(f"   فرق الحرارة: {final_state.delta_T:.1f} كلفن")
    
    # تقييم الطاقة
    print(f"\n🔬 تقييم الطاقة (واقعي):")
    r_p = final_state.d_p / 2
    m_p = (4/3) * np.pi * r_p**3 * solver.rho_ice
    kinetic_energy = 0.5 * m_p * np.linalg.norm(final_state.v_p)**2
    electric_energy = final_state.q_p * np.linalg.norm(final_state.E_field) * 2*r_p
    
    print(f"   طاقة حركة الجسيم: {kinetic_energy:.2e} جول")
    print(f"   طاقة كهربائية: {electric_energy:.2e} جول")
    
    if kinetic_energy > 0:
        ratio = electric_energy / kinetic_energy
        print(f"   نسبة الطاقة الكهربائية/الحركية: {ratio:.2e}")
        
        if ratio > 0.01:
            print(f"   ⚡ التأثير الكهربائي مهم للقياس")
        else:
            print(f"   ⚡ التأثير الكهربائي ضعيف ولكن قابل للقياس")
    
    print("\n" + "="*80)
    print("✅ نموذج العاصفة الثلجية الواقعي والمستقر جاهز!")
    print("="*80)

if __name__ == "__main__":
    main()
