// SPDX-License-Identifier: AGPL-3.0-only
// Copyright (C) 2026 Vallés Puig, Ramon

//! Internal baseline helpers for Criterion benchmarks.
//!
//! Enabled with the `bench-internals` feature; not part of the stable API.
//! Run gated benches with:
//!
//! ```bash
//! cargo bench --features bench-internals --bench solar_altitude
//! cargo bench --features bench-internals --bench moon_altitude
//! ```

use crate::coordinates::centers::Geodetic;
use crate::coordinates::frames::ECEF;
use crate::event::altitude::search::InternalSearchConfig;
use crate::event::altitude::{CrossingEvent, SearchOpts};
use crate::event::search::intervals::LabeledCrossing;
use crate::qtty::*;
use crate::time::{Interval, ModifiedJulianDate};

// Re-export the diagnostics struct so bench binaries can inspect it.
pub use crate::event::solar::daily_events::SolarDailyDiagnostics;

// ---------------------------------------------------------------------------
// Solar baselines
// ---------------------------------------------------------------------------

/// Solar above-threshold using the internal scan+Brent baseline.
pub fn solar_above_threshold_scan_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    threshold: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::solar::solar_above_threshold_impl(
        site,
        window,
        threshold,
        InternalSearchConfig::scan_brent_baseline_config(opts),
    )
}

/// Solar below-threshold using the internal scan+Brent baseline.
pub fn solar_below_threshold_scan_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    threshold: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::solar::solar_below_threshold_impl(
        site,
        window,
        threshold,
        InternalSearchConfig::scan_brent_baseline_config(opts),
    )
}

/// Solar below-threshold using the generic Chebyshev-first engine (daily predictor disabled).
pub fn solar_below_threshold_chebyshev_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    threshold: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::solar::solar_below_threshold_impl(
        site,
        window,
        threshold,
        InternalSearchConfig::chebyshev_baseline_config(opts),
    )
}

/// Solar altitude-range search using the internal scan+Brent baseline.
pub fn solar_altitude_ranges_scan_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    h_min: Degrees,
    h_max: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::solar::solar_altitude_ranges_impl(
        site,
        window,
        (h_min, h_max),
        InternalSearchConfig::scan_brent_baseline_config(opts),
    )
}

/// Solar altitude-range search using the generic Chebyshev-first engine (daily predictor disabled).
pub fn solar_altitude_ranges_chebyshev_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    h_min: Degrees,
    h_max: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::solar::solar_altitude_ranges_impl(
        site,
        window,
        (h_min, h_max),
        InternalSearchConfig::chebyshev_baseline_config(opts),
    )
}

/// Returns diagnostics from the solar daily predictor for one threshold/window.
///
/// Useful in benchmarks and tests to measure `precise_evaluations`,
/// `bracket_failures`, `newton_accepted`, etc.
pub fn solar_daily_diagnostics(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    threshold: Degrees,
    opts: SearchOpts,
) -> SolarDailyDiagnostics {
    crate::event::solar::daily_events::solar_daily_crossings_impl(
        site,
        window,
        threshold,
        InternalSearchConfig::from_public_opts(opts),
    )
    .1
}

/// Batch twilight-profile crossing helper (one daily pass, all thresholds).
///
/// Returns one sorted `Vec<LabeledCrossing>` per threshold entry.
pub fn solar_twilight_profile(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    thresholds: &[Degrees],
    opts: SearchOpts,
) -> Vec<Vec<LabeledCrossing>> {
    crate::event::solar::daily_events::solar_twilight_profile_impl(
        site,
        window,
        thresholds,
        InternalSearchConfig::from_public_opts(opts),
    )
}

/// Solar crossing search using the internal scan+Brent baseline.
pub fn solar_crossings_scan_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    threshold: Degrees,
    opts: SearchOpts,
) -> Vec<CrossingEvent> {
    crate::event::solar::solar_crossings_impl(
        site,
        window,
        threshold,
        InternalSearchConfig::scan_brent_baseline_config(opts),
    )
}

// ---------------------------------------------------------------------------
// Lunar baselines
// ---------------------------------------------------------------------------

/// Lunar above-threshold using the internal scan+Brent baseline.
pub fn lunar_above_threshold_scan_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    threshold: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::lunar::lunar_above_threshold_impl(
        site,
        window,
        threshold,
        InternalSearchConfig::scan_brent_baseline_config(opts),
    )
}

/// Lunar below-threshold using the internal scan+Brent baseline.
pub fn lunar_below_threshold_scan_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    threshold: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::lunar::lunar_below_threshold_impl(
        site,
        window,
        threshold,
        InternalSearchConfig::scan_brent_baseline_config(opts),
    )
}

/// Lunar altitude-range search using the internal scan+Brent baseline.
pub fn lunar_altitude_ranges_scan_baseline(
    site: Geodetic<ECEF>,
    window: Interval<ModifiedJulianDate>,
    h_min: Degrees,
    h_max: Degrees,
    opts: SearchOpts,
) -> Vec<Interval<ModifiedJulianDate>> {
    crate::event::lunar::lunar_altitude_ranges_impl(
        site,
        window,
        (h_min, h_max),
        InternalSearchConfig::scan_brent_baseline_config(opts),
    )
}
