#[cfg(not(coverage))]
#[tokio::main(flavor = "current_thread")]
/// Keeps `main` explicit because it sits on CLI orchestration, where operators need deterministic exits and artifact paths.
/// Inputs are the typed parameters; output is the return value or side effect.
async fn main() -> Result<()> {
    let config = match parse_args()? {
        ParseOutcome::Run(config) => config,
        ParseOutcome::Help => {
            println!("{}", usage());
            return Ok(());
        }
    };

    if config.command == CommandKind::Version {
        let caps = get_server_capabilities(config.server.as_str()).await?;
        print_versions(config.server.as_str(), &caps);
        return Ok(());
    }

    let mut client = connect(config.server.as_str()).await?;

    if let Some(request) = capture_power_request(config.command) {
        let context = match config.command {
            CommandKind::Auto => "setting capture power to auto",
            CommandKind::On => "forcing capture power on",
            CommandKind::Off => "forcing capture power off",
            CommandKind::Status
            | CommandKind::Version
            | CommandKind::CalibrationStatus
            | CommandKind::CalibrationAdjust
            | CommandKind::CalibrationRestoreDefault
            | CommandKind::CalibrationRestoreFactory
            | CommandKind::CalibrationSaveDefault
            | CommandKind::RecoverUsb
            | CommandKind::RecoverUac
            | CommandKind::RecoverUvc
            | CommandKind::ResetUsb
            | CommandKind::UpstreamSync
            | CommandKind::OutputDelayProbe => unreachable!(),
        };
        let reply = client
            .set_capture_power(Request::new(request))
            .await
            .context(context)?
            .into_inner();
        print_state(reply);
        return Ok(());
    }

    if let Some(request) = calibration_request_for(&config) {
        let reply = client
            .calibrate(Request::new(request))
            .await
            .context("applying upstream A/V calibration")?
            .into_inner();
        print_calibration_state(reply);
        return Ok(());
    }

    if config.command == CommandKind::OutputDelayProbe {
        let request = OutputDelayProbeRequest {
            duration_seconds: config.probe_duration_seconds,
            warmup_seconds: config.probe_warmup_seconds,
            pulse_period_ms: config.probe_pulse_period_ms,
            pulse_width_ms: config.probe_pulse_width_ms,
            event_width_codes: config.probe_event_width_codes.clone(),
            audio_delay_us: config.probe_audio_delay_us,
            video_delay_us: config.probe_video_delay_us,
        };
        let mut stream = client
            .run_output_delay_probe(Request::new(request))
            .await
            .context("running server-generated UVC/UAC output-delay probe")?
            .into_inner();
        while let Some(reply) = stream
            .message()
            .await
            .context("reading output-delay probe reply")?
        {
            println!("ok={}", reply.ok);
            println!("detail={}", reply.detail);
            if !reply.server_timeline_json.trim().is_empty() {
                println!("server_timeline_json={}", reply.server_timeline_json);
            }
        }
        return Ok(());
    }

    let reply = match config.command {
        CommandKind::Status => client
            .get_capture_power(Request::new(Empty {}))
            .await
            .context("querying capture power state")?
            .into_inner(),
        CommandKind::RecoverUsb => {
            let reply = client
                .recover_usb(Request::new(Empty {}))
                .await
                .context("requesting soft USB recovery")?
                .into_inner();
            println!("ok={}", reply.ok);
            return Ok(());
        }
        CommandKind::RecoverUac => {
            let reply = client
                .recover_uac(Request::new(Empty {}))
                .await
                .context("requesting soft UAC recovery")?
                .into_inner();
            println!("ok={}", reply.ok);
            return Ok(());
        }
        CommandKind::RecoverUvc => {
            let reply = client
                .recover_uvc(Request::new(Empty {}))
                .await
                .context("requesting soft UVC recovery")?
                .into_inner();
            println!("ok={}", reply.ok);
            return Ok(());
        }
        CommandKind::ResetUsb => {
            let reply = client
                .reset_usb(Request::new(Empty {}))
                .await
                .context("forcing USB gadget recovery")?
                .into_inner();
            println!("ok={}", reply.ok);
            return Ok(());
        }
        CommandKind::UpstreamSync => {
            let reply = client
                .get_upstream_sync(Request::new(Empty {}))
                .await
                .context("querying upstream sync planner state")?
                .into_inner();
            print_upstream_sync(reply);
            return Ok(());
        }
        CommandKind::CalibrationStatus => {
            let reply = client
                .get_calibration(Request::new(Empty {}))
                .await
                .context("querying upstream A/V calibration")?
                .into_inner();
            print_calibration_state(reply);
            return Ok(());
        }
        CommandKind::Version | CommandKind::Auto | CommandKind::On | CommandKind::Off => {
            unreachable!()
        }
        CommandKind::OutputDelayProbe => unreachable!(),
        CommandKind::CalibrationAdjust
        | CommandKind::CalibrationRestoreDefault
        | CommandKind::CalibrationRestoreFactory
        | CommandKind::CalibrationSaveDefault => unreachable!(),
    };

    print_state(reply);
    Ok(())
}
