use anyhow::Context as _;
use clap::{Parser, Subcommand};

use crate::metadata::Instance;

mod metadata;

fn main() {
    common::entrypoint(program);
}

#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
pub struct Args {
    #[command(subcommand)]
    pub command: Commands,
}

#[derive(Debug, Subcommand)]
pub enum Commands {
    /// Configures the ipv6 address using instance metadata and iproute2
    Configure,
}

fn program() -> anyhow::Result<()> {
    let args = Args::parse();
    match args.command {
        Commands::Configure => configure(),
    }
}

fn configure() -> anyhow::Result<()> {
    let metadata_api = common::env::read_env("INSTANCE_API_URI")
        .unwrap_or(String::from("http://169.254.169.254/hetzner/v1/metadata"));
    let metadata = common::curl::read_text_as_string(&metadata_api)?;
    let metadata: Instance = common::yaml::from_str(&metadata)
        .context("Could not parse instance metadata into expected format")?;
    for m in metadata.network_config.config {
        for subnet in m.subnets {
            match subnet {
                metadata::InstanceNetworkConfigConfigSubnet::Static {
                    ipv6,
                    ipv4,
                    address,
                    gateway,
                } => {
                    let mut cmd = common::proc::Command::new("ip");
                    if ipv6.is_some_and(|v| v) {
                        cmd.arg("-6");
                    }
                    if ipv4.is_some_and(|v| v) {
                        cmd.arg("-4");
                    }
                    cmd.args(["addr", "add", &address, "dev", &m.name]);
                    cmd.try_spawn_to_string()?;
                    let mut cmd = common::proc::Command::new("ip");
                    if ipv6.is_some_and(|v| v) {
                        cmd.arg("-6");
                    }
                    if ipv4.is_some_and(|v| v) {
                        cmd.arg("-4");
                    }
                    cmd.args(["route", "add", "default", "via", &gateway, "dev", &m.name]);
                    cmd.try_spawn_to_string()?;
                }
                metadata::InstanceNetworkConfigConfigSubnet::Dhcp {} => continue,
            }
        }
    }
    Ok(())
}
