/*──────────────── main ───────────────────────*/
fn usage_line() -> &'static str {
    "Usage: lesavka-server [--version|-V] [--help|-h]"
}

fn handle_startup_args() -> anyhow::Result<bool> {
    let args = std::env::args().skip(1).collect::<Vec<_>>();
    match args.as_slice() {
        [] => Ok(false),
        [arg] if arg == "--version" || arg == "-V" => {
            println!("{} {}", PKG_NAME, lesavka_server::VERSION);
            Ok(true)
        }
        [arg] if arg == "--help" || arg == "-h" => {
            println!("{}", usage_line());
            Ok(true)
        }
        [arg] if arg.starts_with('-') => {
            let suggestion = if "--version".starts_with(arg.as_str()) {
                "; did you mean --version?"
            } else {
                ""
            };
            anyhow::bail!("unknown option {arg:?}{suggestion}; {}", usage_line())
        }
        [arg] => anyhow::bail!("unexpected positional argument {arg:?}; {}", usage_line()),
        _ => anyhow::bail!("too many arguments; {}", usage_line()),
    }
}

#[cfg(not(coverage))]
#[tokio::main(worker_threads = 4)]
async fn main() -> anyhow::Result<()> {
    if handle_startup_args()? {
        return Ok(());
    }

    let _guard = init_tracing()?;
    info!("🚀 {} v{} starting up", PKG_NAME, lesavka_server::VERSION);

    panic::set_hook(Box::new(|p| {
        let bt = Backtrace::force_capture();
        error!("💥 panic: {p}\n{bt}");
    }));

    let gadget = UsbGadget::new("lesavka");
    if std::env::var("LESAVKA_DISABLE_UVC").is_err() {
        if std::env::var("LESAVKA_UVC_EXTERNAL").is_ok() {
            info!("📷 UVC control helper external; not spawning");
        } else {
            let bin = uvc_runtime::uvc_ctrl_bin();
            tokio::spawn(uvc_runtime::supervise_uvc_control(bin));
        }
    } else {
        info!("📷 UVC disabled (LESAVKA_DISABLE_UVC set)");
    }
    let handler = Handler::new(gadget.clone()).await?;

    let bind_addr = server_bind_addr()?;
    info!("🌐 lesavka-server listening on {bind_addr}");
    let mut server = Server::builder()
        .tcp_nodelay(true)
        .max_frame_size(Some(2 * 1024 * 1024));
    if let Some(tls) = security::server_tls_config()? {
        server = server.tls_config(tls)?;
    }
    server
        .add_service(RelayServer::new(handler))
        .add_service(HandshakeSvc::server())
        .add_service(ReflBuilder::configure().build_v1().unwrap())
        .serve(bind_addr)
        .await?;
    Ok(())
}

#[cfg(coverage)]
#[tokio::main(worker_threads = 2)]
async fn main() -> anyhow::Result<()> {
    if handle_startup_args()? {
        return Ok(());
    }

    let gadget = UsbGadget::new("lesavka");
    let _handler = Handler::new(gadget).await?;
    Err(anyhow::anyhow!("coverage mode skips live gRPC serve loop"))
}
