//! The envelope is the domain contract every surface assembles: pin its
//! construction, its wire shape, and the worst-case freshness mapping.
#![allow(clippy::expect_used, clippy::panic)]

use chrono::{TimeZone, Utc};

use super::{NavdataProvenance, Provenance};
use crate::freshness::Freshness;
use crate::navdata::NavDataCycle;

fn cycle() -> NavDataCycle {
    NavDataCycle::faa_nasr(chrono::NaiveDate::from_ymd_opt(2026, 6, 11).expect("valid"))
        .expect("valid cycle")
}

#[test]
fn envelope_serializes_the_agent_contract() {
    let now = Utc
        .with_ymd_and_hms(2026, 7, 2, 18, 0, 0)
        .single()
        .expect("valid");
    let nav = NavdataProvenance::new(&cycle(), Freshness::Current, "ab12".to_owned());
    let envelope = Provenance::new(now, Freshness::Stale, true, Some(nav));

    let value = serde_json::to_value(&envelope).expect("serializes");
    assert_eq!(value["retrieved_at"], "2026-07-02T18:00:00+00:00");
    assert_eq!(value["freshness"], "stale");
    assert_eq!(value["partial"], true);
    assert_eq!(value["navdata"]["sha256"], "ab12");
    assert_eq!(value["navdata"]["freshness"], "current");
    let cycle_str = value["navdata"]["cycle"].as_str().expect("cycle string");
    assert!(
        cycle_str.contains(".."),
        "cycle is an effective range: {cycle_str}"
    );
}

#[test]
fn freshness_states_map_to_their_wire_strings() {
    for (state, wire) in [
        (Freshness::Current, "current"),
        (Freshness::Stale, "stale"),
        (Freshness::Unknown, "unknown"),
    ] {
        let now = Utc
            .with_ymd_and_hms(2026, 7, 2, 18, 0, 0)
            .single()
            .expect("valid");
        let envelope = Provenance::new(now, state, false, None);
        assert_eq!(envelope.freshness, wire);
    }
}
