pub struct InteriorOceanEndpoint {
    pub wind_speed_m_s: f64,
    pub wind_direction: [f64; 2],
    pub pressure_gpa: f64,
    pub temperature_k: f64,
    pub grid_size: u32,
    pub patch_size_m: f64,
    pub surface_gravity_m_s2: f64,
    pub density_kg_m3: f64,
    pub ior: f64,
    pub absorption_coefficients_rgb_m: [f64; 3],
}

impl InteriorOceanEndpoint {
    pub fn superionic_water() -> Self {
        Self {
            wind_speed_m_s: crate::MAXWINDSMS,
            wind_direction: [1.0, 0.0],
            pressure_gpa: 200.0,
            temperature_k: 2000.0,
            grid_size: 256,
            patch_size_m: 100_000.0,
            surface_gravity_m_s2: *crate::SURFACEGRAVITY,
            density_kg_m3: 1600.0,
            ior: 1.31,
            absorption_coefficients_rgb_m: [0.08, 0.03, 0.01],
        }
    }

    pub fn fresnel_r0(&self) -> f64 {
        ((self.ior - 1.0) / (self.ior + 1.0)).powi(2)
    }

    pub fn wave_amplitude(&self) -> f64 {
        let w = self.wind_speed_m_s.max(0.1);
        let grav = self.surface_gravity_m_s2;
        let alpha_pm = 8.1e-3;
        let beta_pm = 0.74;
        let omega_p = grav / w;
        let pm_peak = alpha_pm * grav * grav / omega_p.powi(5)
            * (-beta_pm * (grav / (omega_p * w)).powi(4)).exp();
        let ocean_dx = self.patch_size_m / self.grid_size as f64;
        let nyquist_k = std::f64::consts::PI / ocean_dx;
        let k_peak = omega_p * omega_p / grav;
        (2.0 * pm_peak / k_peak.min(nyquist_k))
            .sqrt()
            .clamp(0.01, 50.0)
    }

    pub fn depth_color(&self, depth: f64) -> [f64; 3] {
        let d = depth.min(500.0);
        [
            (-self.absorption_coefficients_rgb_m[0] * d).exp(),
            (-self.absorption_coefficients_rgb_m[1] * d).exp(),
            (-self.absorption_coefficients_rgb_m[2] * d).exp(),
        ]
    }
}
