use std::collections::BTreeMap;

use harmony_macros::yaml;
use inquire::Confirm;
use k8s_openapi::{
    api::{
        apps::v1::{Deployment, DeploymentSpec},
        core::v1::{Container, PodSpec, PodTemplateSpec},
    },
    apimachinery::pkg::apis::meta::v1::LabelSelector,
};
use kube::{
    Api, Client, ResourceExt,
    api::{ObjectMeta, PostParams},
};

#[tokio::main]
async fn main() {
    let confirmation = Confirm::new(
        "This will install various ressources to your default kubernetes cluster. Are you sure?",
    )
    .with_default(false)
    .prompt()
    .expect("Unexpected prompt error");

    if !confirmation {
        return;
    }

    let client = Client::try_default()
        .await
        .expect("Should instanciate client from defaults");
    println!("apiserver_version {:?}", client.apiserver_version().await);
    println!("default namespace {:?}", client.default_namespace());
    // println!(
    //     "apiserver_groups {:?}",
    //     client
    //         .list_api_groups()
    //         .await
    //         .unwrap()
    //         .groups
    //         .iter()
    //         .map(|g| g.name.clone())
    //         .collect::<Vec<_>>()
    // );

    // let pods: Api<Pod> = Api::default_namespaced(client.clone());
    // for p in pods.list(&ListParams::default()).await.unwrap() {
    //     println!("found pod {}", p.name_any())
    // }

    // let nodes : Api<Node> = Api::all(client.clone());
    // for n in nodes.list(&ListParams::default()).await.unwrap() {
    //     println!("found node {} status {:?}", n.name_any(), n.status.unwrap())
    // }

    assert_eq!(nginx_deployment(), nginx_macro());
    assert_eq!(nginx_deployment_2(), nginx_macro());
    assert_eq!(nginx_deployment_serde(), nginx_macro());
    let nginxdeployment = nginx_macro();
    let deployment: Api<Deployment> = Api::default_namespaced(client.clone());
    match deployment
        .create(&PostParams::default(), &nginxdeployment)
        .await
    {
        Ok(_d) => println!("Deployment success"),
        Err(e) => {
            println!("Error creating deployment {}", e);
            if let kube::Error::Api(error_response) = &e {
                if error_response.code == http::StatusCode::CONFLICT.as_u16() {
                    println!("Already exists");
                    return;
                }
            }
            panic!("{}", e)
        }
    };
    println!(
        "{:?}",
        deployment
            .get_status(&nginxdeployment.name_unchecked())
            .await
            .unwrap()
    );
    println!("Hello world");
}

fn nginx_macro() -> Deployment {
    yaml!(
        r#"
metadata:
    name: "nginx-test"
spec:
    selector:
        matchLabels:
            app: nginx-test
    template:
        metadata:
            labels:
                app: nginx-test
        spec:
            containers:
                - image: nginx
                  name: nginx"#
    )
    .unwrap()
}

fn nginx_deployment_serde() -> Deployment {
    let deployment: Deployment = serde_yaml::from_str(
        r#"
metadata:
    name: "nginx-test"
spec:
    selector:
        matchLabels:
            app: nginx-test
    template:
        metadata:
            labels:
                app: nginx-test
        spec:
            containers:
                - image: nginx
                  name: nginx"#,
    )
    .unwrap();
    return deployment;
}
fn nginx_deployment_2() -> Deployment {
    let mut pod_template = PodTemplateSpec::default();
    pod_template.metadata = Some(ObjectMeta {
        labels: Some(BTreeMap::from([(
            "app".to_string(),
            "nginx-test".to_string(),
        )])),
        ..Default::default()
    });
    pod_template.spec = Some(PodSpec {
        containers: vec![Container {
            name: "nginx".to_string(),
            image: Some("nginx".to_string()),
            ..Default::default()
        }],
        ..Default::default()
    });
    let mut spec = DeploymentSpec::default();
    spec.template = pod_template;
    spec.selector = LabelSelector {
        match_expressions: None,
        match_labels: Some(BTreeMap::from([(
            "app".to_string(),
            "nginx-test".to_string(),
        )])),
    };

    let mut deployment = Deployment::default();
    deployment.spec = Some(spec);
    deployment.metadata.name = Some("nginx-test".to_string());

    deployment
}

fn nginx_deployment() -> Deployment {
    let deployment = Deployment {
        metadata: ObjectMeta {
            name: Some("nginx-test".to_string()),
            ..Default::default()
        },
        spec: Some(DeploymentSpec {
            min_ready_seconds: None,
            paused: None,
            progress_deadline_seconds: None,
            replicas: Some(1),
            revision_history_limit: Some(10),
            selector: LabelSelector {
                match_expressions: None,
                match_labels: Some(BTreeMap::from([(
                    "app".to_string(),
                    "nginx-test".to_string(),
                )])),
            },
            strategy: None,
            template: PodTemplateSpec {
                metadata: Some(ObjectMeta {
                    labels: Some(BTreeMap::from([(
                        "app".to_string(),
                        "nginx-test".to_string(),
                    )])),
                    ..Default::default()
                }),
                spec: Some(PodSpec {
                    containers: vec![Container {
                        name: "nginx".to_string(),
                        image: Some("nginx".to_string()),
                        ..Default::default()
                    }],
                    ..Default::default()
                }),
            },
        }),
        status: None,
    };
    println!("{:?}", deployment.managed_fields());
    deployment
}
