// src/safety.rs
use defmt::info;
use embassy_time::Duration;

// ISR RX ring capacity = RX_BUF len
const ISR_RX_BUF_CAP: usize = 256;
// Yield 1/2 the time it takes to fill ISR RX ring.
const YIELD_MARGIN_NUM: u32 = 1;
const YIELD_MARGIN_DEN: u32 = 2;
// Ensure RX_PIPE_CAP can hold this.
const WORST_MAIN_LATENCY_MS: u32 = 20;

pub const TX_PIPE_CAP: usize = 1024;
pub const RX_PIPE_CAP: usize = 1024;



/// Perform safety checks and compute yield timing to avoid buffer overflow.
///
/// # Panics
/// Panics if pipe capacities are too small for the configured baud.
pub fn preflight_and_suggest_yield_period(baud: u32) -> Duration {
    // Approx bytes per second for 8N1 (10 bits per byte on the wire)
    let bytes_per_sec = (baud / 10).max(1);

    // Time until ISR RX ring fills, in microseconds.
    let t_fill_us = (ISR_RX_BUF_CAP as u64) * 1_000_000u64 / (bytes_per_sec as u64);

    // Choose a yield period as a fraction of t_fill.
    let yield_us = (t_fill_us as u64)
        .saturating_mul(YIELD_MARGIN_NUM as u64)
        / (YIELD_MARGIN_DEN as u64);

    // Verify RX pipe can absorb a worst-case app latency so uart_task
    // can always forward without dropping when it runs.
    let required_rx_pipe = (bytes_per_sec as u64) * (WORST_MAIN_LATENCY_MS as u64) / 1000;

    if (RX_PIPE_CAP as u64) < required_rx_pipe {
        core::panic!(
            "RX pipe too small: have {}B, need >= {}B for {}ms at {} bps",
            RX_PIPE_CAP, required_rx_pipe, WORST_MAIN_LATENCY_MS, baud
        );
    }

    info!(
        "Preflight: baud={}, rx_isr={}B, rx_pipe={}B, bytes/s={}, t_fill_us={}, yield_us={}",
        baud,
        ISR_RX_BUF_CAP,
        RX_PIPE_CAP,
        bytes_per_sec,
        t_fill_us,
        yield_us
    );

    // Never choose zero.
    Duration::from_micros(yield_us.max(1) as u64)
}
