// Regression contracts for live launcher control behavior.
//
// Scope: source-level assertions around reconnect cooldown, live device
// switching, and gain/control-file propagation.
// Targets: `client/src/launcher/ui/*` and `client/src/launcher/ui_runtime/*`.
// Why: these are the small UI paths operators touch during real calls; stale
// labels or delayed controls make the system feel broken even when transport is healthy.

const UI_SRC: &str = concat!(
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui/media_device_bindings.rs"
    )),
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui/control_requests.rs"
    )),
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui/relay_input_bindings.rs"
    )),
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui/runtime_poll.rs"
    )),
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui/message_and_network_state.rs"
    )),
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui_runtime/control_paths.rs"
    )),
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui/eye_capture_bindings.rs"
    )),
    include_str!(concat!(
        env!("CARGO_MANIFEST_DIR"),
        "/client/src/launcher/ui/utility_button_bindings.rs"
    )),
);

#[test]
fn live_device_and_gain_controls_write_runtime_files_while_relay_is_active() {
    for marker in [
        "apply_live_media_device_change(",
        "{feed_label} selection applied to the live relay; the stream is restarting.",
        "write_media_control_request(&path, state_snapshot)",
        "write_audio_gain_request(&path, percent)",
        "write_mic_gain_request(&path, percent)",
        "Remote audio gain set to {label}.",
        "Mic gain set to {label}.",
    ] {
        assert!(
            UI_SRC.contains(marker),
            "live controls should preserve marker {marker}"
        );
    }
}

#[test]
fn disconnect_button_stays_locked_during_startup_audio_refresh() {
    for marker in [
        "disconnect_cooldown_remaining(",
        "disconnect_cooldown_status(remaining)",
        "Upstream audio is refreshing; disconnect unlocks in {seconds}s.",
        "disconnect_cooldown_until.set(Some(",
        "widgets.start_button.set_sensitive(false);",
        ".start_button\n                            .set_tooltip_text(Some(&disconnect_cooldown_status(remaining)));",
    ] {
        assert!(
            UI_SRC.contains(marker),
            "disconnect cooldown should preserve marker {marker}"
        );
    }
}

#[test]
fn eye_clip_record_save_and_calibration_buttons_remain_bound_to_actions() {
    for marker in [
        "pane.clip_button.connect_clicked",
        "clip saved to",
        "record_button.connect_clicked",
        "recording saved to",
        "pane.save_button.connect_clicked",
        "Choose Eye Capture Folder",
        "widgets.calibration_default_button.connect_clicked",
        "restore_default_calibration(server_addr)",
        "widgets.calibration_factory_button.connect_clicked",
        "restore_factory_calibration(server_addr)",
        "widgets.calibration_minus_button.connect_clicked",
        "nudge_audio_calibration(server_addr, -5_000)",
        "widgets.calibration_plus_button.connect_clicked",
        "nudge_audio_calibration(server_addr, 5_000)",
        "widgets.calibration_blind_button.connect_clicked",
        "blind_calibration_estimate(",
    ] {
        assert!(
            UI_SRC.contains(marker),
            "button action should preserve marker {marker}"
        );
    }
}
