// Decode and persist an admin-UI deploy blob.
//
// The rustdesk-server admin UI emits a config string in two compatible forms,
// both handled by `librustdesk::custom_server::get_custom_server_from_string`:
//
//   1. A reversed URL-safe-base64-encoded JSON object containing
//      {host, key, api, relay}. Example: `0nI900VsFHZ...`
//
//   2. A filename-style blob `host=server.example.net,key=...,api=...,relay=...`
//      (used when the installer is renamed by the admin UI to deliver config).
//
// We treat the input as opaque, append `.exe` if missing (the upstream
// decoder strips it back off), and persist the four resulting fields via
// `hbb_common::config::Config::set_option`. Identical to what
// `core_main.rs` does on `--config` in stock rustdesk
// (see [src/core_main.rs:478](../rustdesk/src/core_main.rs#L478)) — we
// just don't gate it on `is_installed()` since we run before the service
// is registered (one-line MDM deploy: `--install --config <BLOB>`).

use anyhow::{anyhow, Result};
use hbb_common::config::Config;
use librustdesk::custom_server;

/// Built-in fallback rendezvous configuration. Applied by
/// `apply_defaults_if_empty` when no `--config <BLOB>` was provided and
/// no prior install left a value behind. The key here is the public
/// signing key of the cybnet rustdesk-server (`rd.gamecom.ch`) — distinct
/// from the per-agent identity keypair that the agent generates locally
/// on first run.
const DEFAULT_RENDEZVOUS_HOST: &str = "rd.gamecom.ch";
const DEFAULT_API_URL: &str = "https://rd.gamecom.ch";
const DEFAULT_RELAY_HOST: &str = "rd.gamecom.ch";
const DEFAULT_PUBLIC_KEY: &str = "tcxma69cN3OWt25jQ75apSCtaZGIfDqIIP6yGNj3dgs=";

pub fn apply(blob: &str) -> Result<()> {
    let probe = if blob.to_lowercase().ends_with(".exe") {
        blob.to_string()
    } else {
        format!("{blob}.exe")
    };

    let lic = custom_server::get_custom_server_from_string(&probe)
        .map_err(|e| anyhow!("decode failed: {e}"))?;

    if lic.host.is_empty() {
        return Err(anyhow!(
            "config blob decoded but contains no rendezvous host"
        ));
    }

    log::info!(
        "applying config: host={} api={} relay={} key.len={}",
        lic.host,
        lic.api,
        lic.relay,
        lic.key.len(),
    );

    Config::set_option("key".into(), lic.key);
    Config::set_option("custom-rendezvous-server".into(), lic.host);
    Config::set_option("api-server".into(), lic.api);
    Config::set_option("relay-server".into(), lic.relay);

    Ok(())
}

/// Apply the built-in fallback rendezvous config if no `custom-rendezvous-server`
/// is currently set. Idempotent: a prior `--install --config <BLOB>` (or
/// any earlier explicit configuration) wins, and re-runs without `--config`
/// don't clobber it.
///
/// Why this exists: an MDM deployment that just runs `hello-agent.exe --install`
/// (no blob) needs *something* to register against. The defaults baked in
/// here are the cybnet `rd.gamecom.ch` rustdesk-server, so a no-arg install
/// produces a working agent out of the box. Operators who target a
/// different server still pass `--config <BLOB>` and the defaults are
/// skipped.
pub fn apply_defaults_if_empty() {
    if !Config::get_option("custom-rendezvous-server").is_empty() {
        log::info!("custom-rendezvous-server already set; built-in defaults skipped");
        return;
    }
    log::info!(
        "no rendezvous configured; applying built-in defaults: host={} api={} relay={}",
        DEFAULT_RENDEZVOUS_HOST,
        DEFAULT_API_URL,
        DEFAULT_RELAY_HOST,
    );
    Config::set_option("key".into(), DEFAULT_PUBLIC_KEY.into());
    Config::set_option("custom-rendezvous-server".into(), DEFAULT_RENDEZVOUS_HOST.into());
    Config::set_option("api-server".into(), DEFAULT_API_URL.into());
    Config::set_option("relay-server".into(), DEFAULT_RELAY_HOST.into());
}
