use std::collections::BTreeMap;

use kube::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use crate::modules::monitoring::kube_prometheus::types::Operator;

#[derive(CustomResource, Serialize, Deserialize, Debug, Clone, JsonSchema)]
#[kube(
    group = "monitoring.coreos.com",
    version = "v1",
    kind = "Prometheus",
    plural = "prometheuses",
    namespaced
)]
#[serde(rename_all = "camelCase")]
pub struct PrometheusSpec {
    pub service_account_name: String,
    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub service_monitor_namespace_selector: Option<LabelSelector>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub service_monitor_selector: Option<LabelSelector>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub service_discovery_role: Option<String>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub pod_monitor_selector: Option<LabelSelector>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub rule_selector: Option<LabelSelector>,

    #[serde(default, skip_serializing_if = "Option::is_none")]
    pub rule_namespace_selector: Option<LabelSelector>,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct LabelSelector {
    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
    pub match_labels: BTreeMap<String, String>,

    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub match_expressions: Vec<LabelSelectorRequirement>,
}

#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct LabelSelectorRequirement {
    pub key: String,
    pub operator: Operator,
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub values: Vec<String>,
}

impl Default for PrometheusSpec {
    fn default() -> Self {
        PrometheusSpec {
            service_account_name: "prometheus".into(),

            // null means "only my namespace"
            service_monitor_namespace_selector: None,

            // empty selector means match all ServiceMonitors in that namespace
            service_monitor_selector: Some(LabelSelector::default()),

            service_discovery_role: Some("Endpoints".into()),

            pod_monitor_selector: None,

            rule_selector: None,

            rule_namespace_selector: Some(LabelSelector::default()),
        }
    }
}
