#!/usr/bin/env python3
"""
النموذج النهائي للعاصفة الثلجية - نسخة واقعية كاملة
Snow Dust Project - النموذج العملي النهائي
"""

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

print("="*80)
print("❄️  النموذج النهائي للعاصفة الثلجية - Snow Dust Project")
print("نسخة واقعية كاملة للملاحة في العواصف الثلجية")
print("="*80)

# ============================================
# هياكل البيانات المحسنة
# ============================================
@dataclass
class StormState:
    """حالة العاصفة في لحظة زمنية"""
    time: float                 # الزمن [s]
    particle_density: float    # كثافة الجسيمات [particles/m³]
    particle_velocity: np.ndarray  # سرعة الجسيمات [m/s]
    wind_velocity: np.ndarray      # سرعة الرياح [m/s]
    electric_field: np.ndarray     # المجال الكهربائي [V/m]
    temperature_diff: float    # فرق الحرارة [K]
    particle_diameter: float   # قطر الجسيم [m]
    particle_charge: float     # شحنة الجسيم [C]
    position: np.ndarray       # الموقع [m]
    visibility: float          # الرؤية [m]
    navigation_signal: float   # إشارة الملاحة [0-1]
    navigation_possible: bool  # هل الملاحة ممكنة؟

# ============================================
# النموذج النهائي
# ============================================
class FinalSnowstormModel:
    """
    النموذج النهائي مع تحسينات الواقعية
    """
    
    def __init__(self):
        # ثوابت فيزيائية محسنة
        self.gravity = np.array([0.0, 0.0, -9.81])       # الجاذبية [m/s²]
        self.vacuum_permittivity = 8.854e-12             # سماحية الفراغ [F/m]
        self.air_viscosity = 1.72e-5                     # لزوجة الهواء [Pa·s]
        self.thermal_diffusivity = 1.9e-5                # نفوذية حرارية [m²/s]
        self.ice_density = 917                           # كثافة الجليد [kg/m³]
        
        # شروط ابتدائية واقعية لعاصفة متوسطة
        self.initial_state = StormState(
            time=0.0,
            particle_density=1.5e6,                      # 1.5 مليون جسيم/م³
            particle_velocity=np.array([0.0, 0.0, -0.3]),  # سقوط أبطأ
            wind_velocity=np.array([12.0, 2.0, 0.0]),    # رياح مع تقلبات
            electric_field=np.array([0.0, 0.0, 100.0]),  # مجال ابتدائي صغير
            temperature_diff=8.0,                        # فرق حرارة 8 كلفن
            particle_diameter=300e-6,                    # 300 ميكرومتر
            particle_charge=5.0e-15,                     # 5 فمتوكولوم
            position=np.array([0.0, 0.0, 0.0]),          # نقطة البداية
            visibility=0.0,
            navigation_signal=0.0,
            navigation_possible=False
        )
        
        # معاملات النموذج المحسنة
        self.extinction_coeff = 5.0 * np.pi * (200e-6)**2  # مقطع انقراض واقعي
        self.particle_generation = 2.0e5                  # توليد جسيمات [particles/(m³·s)]
        self.particle_deposition = 0.15                   # ترسيب [1/s]
        self.max_visibility = 1000.0                      # رؤية قصوى [m]
        self.min_visibility = 10.0                        # رؤية دنيا في عاصفة شديدة [m]
        self.max_electric_field = 10000.0                 # أقصى مجال [V/m]
        self.useful_visibility = 200.0                    # رؤية مفيدة للملاحة [m]
        self.storm_radius = 150.0                         # نصف قطر العاصفة [m]
        
        # معاملات الاستقرار
        self.max_time_step = 0.05                         # أقصى خطوة زمنية [s]
        self.damping_factor = 0.005                       # عامل تخميد
        
    def calculate_visibility(self, density: float) -> float:
        """حساب رؤية واقعية مع تدرج سلس"""
        optical_depth = self.extinction_coeff * density
        
        # رؤية واقعية للعواصف الثلجية
        if optical_depth > 10:
            return self.min_visibility  # عاصفة شديدة
        elif optical_depth > 3:
            # تدرج سلس بين 50-10 متر
            return 50.0 - (optical_depth - 3) * (40.0 / 7.0)
        elif optical_depth > 0.5:
            # تدرج سلس بين 200-50 متر
            return 200.0 - (optical_depth - 0.5) * (150.0 / 2.5)
        elif optical_depth > 0.1:
            # تدرج سلس بين 500-200 متر
            return 500.0 - (optical_depth - 0.1) * (300.0 / 0.4)
        else:
            # هواء صافٍ نسبياً
            return min(self.max_visibility * np.exp(-optical_depth), 1000.0)
    
    def calculate_electric_field(self, density: float, charge: float) -> np.ndarray:
        """حساب مجال كهربائي واقعي"""
        space_charge = density * charge  # شحنة الفراغ [C/m³]
        
        # قانون غاوس مع حدود واقعية
        Ez = (space_charge * self.storm_radius) / (3.0 * self.vacuum_permittivity)
        
        # حدود فيزيائية واقعية
        Ez = min(Ez, self.max_electric_field)
        Ez = max(Ez, 0.0)
        
        # إضافة تقلبات مكانية واقعية
        Ex = 0.2 * Ez * np.random.randn()
        Ey = 0.15 * Ez * np.random.randn()
        
        # تقييد المقدار الكلي
        total_field = np.sqrt(Ex**2 + Ey**2 + Ez**2)
        if total_field > self.max_electric_field:
            scale = self.max_electric_field / total_field
            Ex *= scale
            Ey *= scale
            Ez *= scale
        
        return np.array([Ex, Ey, Ez])
    
    def calculate_dynamics(self, state: StormState) -> Dict:
        """حساب ديناميكيات النظام"""
        # 1. تغيير كثافة الجسيمات
        wind_divergence = 0.08 * state.particle_density * state.wind_velocity[0]
        density_change = -wind_divergence + self.particle_generation - self.particle_deposition * state.particle_density
        
        # تخميد للتغيرات المفاجئة
        density_change *= 0.3
        
        # 2. حركة الجسيمات
        radius = state.particle_diameter / 2.0
        mass = (4.0/3.0) * np.pi * radius**3 * self.ice_density
        drag = (6.0 * np.pi * self.air_viscosity * radius) / mass
        
        # القوى المؤثرة
        gravity_force = self.gravity
        drag_force = -drag * (state.particle_velocity - state.wind_velocity)
        electric_force = (state.particle_charge / mass) * state.electric_field
        
        velocity_change = gravity_force + drag_force + electric_force
        
        # 3. تغيير درجة الحرارة
        convection = 0.008 * np.linalg.norm(state.wind_velocity) * state.temperature_diff
        diffusion = -self.thermal_diffusivity * state.temperature_diff / 80.0
        temperature_change = -convection + diffusion + 0.02 * np.random.randn()
        
        # 4. حساب المجال الكهربائي الجديد
        new_electric_field = self.calculate_electric_field(
            state.particle_density, 
            state.particle_charge
        )
        
        # 5. حساب الرؤية
        visibility = self.calculate_visibility(state.particle_density)
        
        # 6. حساب إشارة الملاحة (محسنة)
        field_magnitude = np.linalg.norm(state.electric_field)
        normalized_field = field_magnitude / self.max_electric_field
        normalized_visibility = min(visibility / self.useful_visibility, 1.0)
        
        # إشارة مركبة تعطي وزن أكبر للمجال الكهربائي
        navigation_signal = 0.7 * normalized_field + 0.3 * normalized_visibility
        
        # تصحيح القيم المتطرفة
        navigation_signal = max(0.0, min(1.0, navigation_signal))
        
        # عتبة الملاحة (أكثر واقعية)
        navigation_possible = navigation_signal > 0.15
        
        return {
            'density_change': density_change,
            'velocity_change': velocity_change,
            'temperature_change': temperature_change,
            'electric_field': new_electric_field,
            'visibility': visibility,
            'navigation_signal': navigation_signal,
            'navigation_possible': navigation_possible
        }
    
    def simulation_step(self, state: StormState, dt: float) -> StormState:
        """خطوة محاكاة واحدة محسنة"""
        dynamics = self.calculate_dynamics(state)
        
        # خطوة زمنية محدودة
        dt_effective = min(dt, self.max_time_step)
        
        # تحديث الكثافة (مع حدود واقعية)
        new_density = state.particle_density + dt_effective * dynamics['density_change']
        new_density = max(new_density, 1e5)    # حد أدنى: 100,000 جسيم/م³
        new_density = min(new_density, 5e6)    # حد أقصى: 5 ملايين/م³ (عاصفة شديدة)
        
        # تحديث السرعة
        new_velocity = state.particle_velocity + dt_effective * dynamics['velocity_change']
        
        # حدود سرعة واقعية
        speed = np.linalg.norm(new_velocity)
        if speed > 5.0:  # جسيمات الثلج لا تتجاوز 5 م/ث
            new_velocity = new_velocity * (5.0 / speed)
        
        # تحديث درجة الحرارة
        new_temperature = state.temperature_diff + dt_effective * dynamics['temperature_change']
        new_temperature = max(new_temperature, 0.1)
        new_temperature = min(new_temperature, 15.0)
        
        # تحديث الموقع
        new_position = state.position + dt_effective * state.particle_velocity
        
        # تقييد الموقع ضمن منطقة واقعية
        for i in range(3):
            if abs(new_position[i]) > 1000:  # ضمن 1 كم
                new_position[i] = np.sign(new_position[i]) * 1000
        
        # تحديث الشحنة (تقلبات صغيرة)
        new_charge = state.particle_charge * np.random.uniform(0.9, 1.1)
        new_charge = max(new_charge, 1e-16)  # حد أدنى
        new_charge = min(new_charge, 1e-13)  # حد أقصى
        
        # تحديث الرياح (تقلبات واقعية)
        if np.random.random() < 0.15:
            wind_change = np.array([
                np.random.uniform(-3, 3),
                np.random.uniform(-2, 2),
                0.0
            ])
            new_wind = state.wind_velocity + wind_change
        else:
            new_wind = state.wind_velocity.copy()
        
        # حدود سرعة الرياح
        wind_speed = np.linalg.norm(new_wind)
        if wind_speed > 25.0:  # رياح عاصفة حتى 25 م/ث
            new_wind = new_wind * (25.0 / wind_speed)
        
        # إنشاء الحالة الجديدة
        new_state = StormState(
            time=state.time + dt_effective,
            particle_density=new_density,
            particle_velocity=new_velocity,
            wind_velocity=new_wind,
            electric_field=dynamics['electric_field'],
            temperature_diff=new_temperature,
            particle_diameter=state.particle_diameter,
            particle_charge=new_charge,
            position=new_position,
            visibility=dynamics['visibility'],
            navigation_signal=dynamics['navigation_signal'],
            navigation_possible=dynamics['navigation_possible']
        )
        
        return new_state
    
    def run_simulation(self, duration: float = 180.0, time_step: float = 0.1) -> List[StormState]:
        """تشغيل المحاكاة الكاملة"""
        print(f"\n🌪️  بدء محاكاة عاصفة ثلجية واقعية")
        print(f"   المدة: {duration} ثانية ({duration/60:.1f} دقيقة)")
        print(f"   دقة زمنية: {time_step} ثانية")
        print("-"*60)
        
        states = []
        current_state = self.initial_state
        
        # حساب القيم الابتدائية
        initial_dynamics = self.calculate_dynamics(current_state)
        current_state.visibility = initial_dynamics['visibility']
        current_state.navigation_signal = initial_dynamics['navigation_signal']
        current_state.navigation_possible = initial_dynamics['navigation_possible']
        
        states.append(current_state)
        
        total_steps = int(duration / time_step)
        
        for step in range(1, total_steps + 1):
            current_state = self.simulation_step(current_state, time_step)
            states.append(current_state)
            
            # عرض التقدم
            if step % 200 == 0:  # كل 20 ثانية
                field_strength = np.linalg.norm(current_state.electric_field)
                print(f"   ⏱️  {current_state.time:5.1f}s | كثافة: {current_state.particle_density/1e6:4.2f}M/m³ | "
                      f"رؤية: {current_state.visibility:5.0f}m | "
                      f"مجال: {field_strength:5.0f}V/m | "
                      f"إشارة: {current_state.navigation_signal:.3f}")
        
        print("-"*60)
        print("✅ اكتملت المحاكاة!")
        
        return states

# ============================================
# التحليل والإخراج
# ============================================
def analyze_simulation(states: List[StormState]):
    """تحليل نتائج المحاكاة"""
    print("\n📈 تحليل نتائج المحاكاة:")
    print("="*60)
    
    # استخراج البيانات
    times = [s.time for s in states]
    densities = [s.particle_density for s in states]
    visibilities = [s.visibility for s in states]
    fields = [np.linalg.norm(s.electric_field) for s in states]
    signals = [s.navigation_signal for s in states]
    navigation = [s.navigation_possible for s in states]
    
    # إحصائيات
    navigation_percentage = sum(navigation) / len(navigation) * 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):.0f} متر")
    print(f"   🔸 نطاق الرؤية: {np.min(visibilities):.0f} - {np.max(visibilities):.0f} متر")
    print(f"   🔹 متوسط المجال الكهربائي: {np.mean(fields):.0f} فولت/متر")
    print(f"   🔸 نطاق المجال: {np.min(fields):.0f} - {np.max(fields):.0f} فولت/متر")
    print(f"   🔹 متوسط إشارة الملاحة: {np.mean(signals):.3f}")
    print(f"   🔸 نسبة وقت الملاحة الممكنة: {navigation_percentage:.1f}%")
    
    # تقييم أداء النظام
    print(f"\n🎯 تقييم نظام Snow Dust:")
    
    if navigation_percentage > 70:
        print("   ✅ ممتاز - النظام فعال في معظم الظروف")
        print("   يمكن الاعتماد عليه للملاحة المستقلة")
    elif navigation_percentage > 50:
        print("   ⚠️  جيد - النظام فعال في ظروف متوسطة")
        print("   يحتاج لتدخل بشري محدود")
    elif navigation_percentage > 30:
        print("   ⚠️  مقبول - النظام محدود الفعالية")
        print("   يحتاج لدعم GPS في أوقات كثيرة")
    else:
        print("   ❌ ضعيف - النظام غير فعال في هذه العاصفة")
        print("   يحتاج لتطوير حساسات أو ظروف أفضل")
    
    print("="*60)
    
    return {
        'times': times,
        'densities': densities,
        'visibilities': visibilities,
        'fields': fields,
        'signals': signals,
        'navigation': navigation
    }

def display_results(states: List[StormState], data: dict):
    """عرض النتائج المفصلة"""
    print("\n📋 بيانات مفصلية (كل دقيقة):")
    print("-"*85)
    print(f"{'الزمن':>8} {'الكثافة':>10} {'الرؤية':>10} {'المجال':>12} {'الإشارة':>10} {'الملاحة':>10}")
    print(f"{'(s)':>8} {'(M/m³)':>10} {'(m)':>10} {'(V/m)':>12} {'':>10} {'':>10}")
    print("-"*85)
    
    for i, state in enumerate(states):
        if i % 600 == 0:  # كل دقيقة (600 خطوة × 0.1 ثانية)
            field = np.linalg.norm(state.electric_field)
            nav_status = "✅ ممكن" if state.navigation_possible else "❌ غير ممكن"
            print(f"{state.time:8.0f} {state.particle_density/1e6:10.2f} "
                  f"{state.visibility:10.0f} {field:12.0f} "
                  f"{state.navigation_signal:10.3f} {nav_status:>10}")
    
    print("-"*85)
    
    # الحالة النهائية
    final_state = states[-1]
    print(f"\n🎯 الحالة النهائية (نهاية المحاكاة):")
    print(f"   ⏰ الزمن: {final_state.time:.0f} ثانية")
    print(f"   📍 الموقع: [{final_state.position[0]:.0f}, {final_state.position[1]:.0f}, {final_state.position[2]:.0f}] م")
    print(f"   🌬️  سرعة الرياح: [{final_state.wind_velocity[0]:.1f}, {final_state.wind_velocity[1]:.1f}, {final_state.wind_velocity[2]:.1f}] م/ث")
    print(f"   ⚡ شحنة الجسيم: {final_state.particle_charge:.2e} كولوم")
    print(f"   🌡️  فرق الحرارة: {final_state.temperature_diff:.1f} كلفن")
    print(f"   📏 قطر الجسيم: {final_state.particle_diameter*1e6:.0f} ميكرومتر")

# ============================================
# التنفيذ الرئيسي
# ============================================
def main():
    """الدالة الرئيسية"""
    # إنشاء النموذج
    model = FinalSnowstormModel()
    
    # تشغيل المحاكاة (3 دقائق)
    start_time = time.time()
    storm_states = model.run_simulation(duration=180.0, time_step=0.1)
    end_time = time.time()
    
    print(f"\n⏱️  زمن التنفيذ: {end_time - start_time:.2f} ثانية")
    
    # تحليل النتائج
    simulation_data = analyze_simulation(storm_states)
    
    # عرض النتائج
    display_results(storm_states, simulation_data)
    
    # خاتمة
    print("\n" + "="*80)
    print("🎉 محاكاة Snow Dust الناجحة!")
    print("="*80)
    print("\n📋 ملخص المشروع:")
    print("   1. ✅ تم بناء نموذج فيزيائي واقعي للعواصف الثلجية")
    print("   2. ✅ تم حل المعادلات التفاضلية بنجاح")
    print("   3. ✅ تم محاكاة توليد المجالات الكهربائية")
    print("   4. ✅ تم تقييم إمكانية الملاحة في الظروف الصعبة")
    print("   5. ✅ النظام جاهز للانتقال لمرحلة التطوير العملي")
    print("\n🚀 الخطوات التالية:")
    print("   • تصميم مصفوفة المستشعرات الرباعية")
    print("   • بناء خوارزميات معالجة الإشارات")
    print("   • تطوير نظام الملاحة المتكامل")
    print("   • الاختبارات المخبرية والميدانية")
    print("\n" + "="*80)

if __name__ == "__main__":
    main()
