use sciforge::hub::prelude::constants::elements::atomic_mass;

pub struct ExosphereSpecies {
    pub name: &'static str,
    pub symbol: &'static str,
    pub atomic_number: u32,
    pub molar_mass_kg_mol: f64,
    pub column_density_cm2: f64,
    pub scale_height_km: f64,
    pub source_mechanism: &'static str,
}

pub struct ExosphereEndpoint {
    pub planet_radius_m: f64,
    pub surface_pressure_pa: f64,
    pub species: Vec<ExosphereSpecies>,
    pub solar_wind_sputtering_rate: f64,
}

impl ExosphereEndpoint {
    pub fn mercury() -> Self {
        Self {
            planet_radius_m: 2_439_700.0,
            surface_pressure_pa: crate::EXOSPHERE_SURFACE_PRESSURE_PA,
            species: vec![
                ExosphereSpecies {
                    name: "Sodium",
                    symbol: "Na",
                    atomic_number: 11,
                    molar_mass_kg_mol: atomic_mass(11) * 1e-3,
                    column_density_cm2: crate::NA_COLUMN_DENSITY,
                    scale_height_km: crate::NA_SCALE_HEIGHT_KM,
                    source_mechanism: "photon-stimulated desorption + sputtering",
                },
                ExosphereSpecies {
                    name: "Potassium",
                    symbol: "K",
                    atomic_number: 19,
                    molar_mass_kg_mol: atomic_mass(19) * 1e-3,
                    column_density_cm2: crate::K_COLUMN_DENSITY,
                    scale_height_km: crate::K_SCALE_HEIGHT_KM,
                    source_mechanism: "photon-stimulated desorption",
                },
                ExosphereSpecies {
                    name: "Helium",
                    symbol: "He",
                    atomic_number: 2,
                    molar_mass_kg_mol: atomic_mass(2) * 1e-3,
                    column_density_cm2: crate::HE_COLUMN_DENSITY,
                    scale_height_km: crate::HE_SCALE_HEIGHT_KM,
                    source_mechanism: "solar wind capture + radiogenic",
                },
                ExosphereSpecies {
                    name: "Calcium",
                    symbol: "Ca",
                    atomic_number: 20,
                    molar_mass_kg_mol: atomic_mass(20) * 1e-3,
                    column_density_cm2: crate::CA_COLUMN_DENSITY,
                    scale_height_km: 50.0,
                    source_mechanism: "meteoroid impact vaporization",
                },
                ExosphereSpecies {
                    name: "Magnesium",
                    symbol: "Mg",
                    atomic_number: 12,
                    molar_mass_kg_mol: atomic_mass(12) * 1e-3,
                    column_density_cm2: crate::MG_COLUMN_DENSITY,
                    scale_height_km: 65.0,
                    source_mechanism: "meteoroid impact + sputtering",
                },
                ExosphereSpecies {
                    name: "Oxygen",
                    symbol: "O",
                    atomic_number: 8,
                    molar_mass_kg_mol: atomic_mass(8) * 1e-3,
                    column_density_cm2: crate::O_COLUMN_DENSITY,
                    scale_height_km: 150.0,
                    source_mechanism: "photodissociation of surface oxides",
                },
                ExosphereSpecies {
                    name: "Hydrogen",
                    symbol: "H",
                    atomic_number: 1,
                    molar_mass_kg_mol: atomic_mass(1) * 1e-3,
                    column_density_cm2: crate::H_COLUMN_DENSITY,
                    scale_height_km: 400.0,
                    source_mechanism: "solar wind proton neutralization",
                },
            ],
            solar_wind_sputtering_rate: 1.0e24,
        }
    }

    pub fn density_at_altitude(&self, species_symbol: &str, altitude_km: f64) -> f64 {
        if let Some(s) = self.species.iter().find(|sp| sp.symbol == species_symbol) {
            s.column_density_cm2 / (s.scale_height_km * 1e5)
                * (-altitude_km / s.scale_height_km).exp()
        } else {
            0.0
        }
    }

    pub fn sodium_glow_intensity(&self, sun_distance_au: f64) -> f64 {
        let base = 1.0e6;
        base / (sun_distance_au * sun_distance_au)
    }

    pub fn total_column_density(&self) -> f64 {
        self.species.iter().map(|s| s.column_density_cm2).sum()
    }
}

pub fn scattering_coefficients() -> (f64, f64) {
    (0.0, 0.0)
}

pub fn rayleigh_coefficients() -> [f64; 3] {
    [0.0, 0.0, 0.0]
}

pub fn mie_coefficient() -> f64 {
    0.0
}

pub fn optical_depth(altitude_m: f64, zenith_cos: f64) -> f64 {
    if altitude_m.is_finite() && zenith_cos.is_finite() {
        0.0
    } else {
        f64::NAN
    }
}

pub fn sky_color(sun_elevation_rad: f64) -> [f32; 3] {
    if sun_elevation_rad.is_finite() {
        [0.0, 0.0, 0.0]
    } else {
        [f32::NAN; 3]
    }
}

pub fn sodium_glow_intensity(sun_distance_au: f64) -> f64 {
    let base = 1.0e6;
    base / (sun_distance_au * sun_distance_au)
}
