use super::config::KubePrometheusConfig;
use log::info;
use non_blank_string_rs::NonBlankString;
use std::str::FromStr;

use crate::modules::helm::chart::HelmChartScore;

pub fn kube_prometheus_helm_chart_score() -> HelmChartScore {
    let config = KubePrometheusConfig::new();

    //TODO this should be make into a rule with default formatting that can be easily passed as a vec
    //to the overrides or something leaving the user to deal with formatting here seems bad
    let default_rules = config.default_rules.to_string();
    let windows_monitoring = config.windows_monitoring.to_string();
    let alert_manager = config.alert_manager.to_string();
    let grafana = config.grafana.to_string();
    let kubernetes_service_monitors = config.kubernetes_service_monitors.to_string();
    let kubernetes_api_server = config.kubernetes_api_server.to_string();
    let kubelet = config.kubelet.to_string();
    let kube_controller_manager = config.kube_controller_manager.to_string();
    let core_dns = config.core_dns.to_string();
    let kube_etcd = config.kube_etcd.to_string();
    let kube_scheduler = config.kube_scheduler.to_string();
    let kube_proxy = config.kube_proxy.to_string();
    let kube_state_metrics = config.kube_state_metrics.to_string();
    let node_exporter = config.node_exporter.to_string();
    let prometheus_operator = config.prometheus_operator.to_string();
    let prometheus = config.prometheus.to_string();
    let mut values = format!(
        r#"
additionalPrometheusRulesMap:
  pods-status-alerts:
    groups:
      - name: pods
        rules:
          - alert: "[CRIT] POD not healthy"
            expr: min_over_time(sum by (namespace, pod) (kube_pod_status_phase{{phase=~"Pending|Unknown|Failed"}})[15m:1m]) > 0
            for: 0m
            labels:
              severity: critical
            annotations:
              title: "[CRIT] POD not healthy : {{{{ $labels.pod }}}}"
              description: |
               A POD is in a non-ready state!
               - **Pod**: {{{{ $labels.pod }}}}
               - **Namespace**: {{{{ $labels.namespace }}}}
          - alert: "[CRIT] POD crash looping"
            expr: increase(kube_pod_container_status_restarts_total[5m]) > 3
            for: 0m
            labels:
              severity: critical
            annotations:
              title: "[CRIT] POD crash looping : {{{{ $labels.pod }}}}"
              description: |
               A POD is drowning in a crash loop!
               - **Pod**: {{{{ $labels.pod }}}}
               - **Namespace**: {{{{ $labels.namespace }}}}
               - **Instance**: {{{{ $labels.instance }}}}
  pvc-alerts:
    groups:
      - name: pvc-alerts
        rules:
          - alert: 'PVC Fill Over 95 Percent In 2 Days'
            expr: |
              (
                kubelet_volume_stats_used_bytes 
                / 
                kubelet_volume_stats_capacity_bytes
              ) > 0.95
              AND
              predict_linear(kubelet_volume_stats_used_bytes[2d], 2 * 24 * 60 * 60)
              / 
              kubelet_volume_stats_capacity_bytes 
              > 0.95
            for: 1m
            labels:
              severity: warning
            annotations:
              description: The PVC {{{{ $labels.persistentvolumeclaim }}}} in namespace {{{{ $labels.namespace }}}} is predicted to fill over 95% in less than 2 days.
              title: PVC {{{{ $labels.persistentvolumeclaim }}}} in namespace {{{{ $labels.namespace }}}} will fill over 95% in less than 2 days
defaultRules:
  create: {default_rules}
  rules:
    alertmanager: true
    etcd: true
    configReloaders: true
    general: true
    k8sContainerCpuUsageSecondsTotal: true
    k8sContainerMemoryCache: true
    k8sContainerMemoryRss: true
    k8sContainerMemorySwap: true
    k8sContainerResource: true
    k8sContainerMemoryWorkingSetBytes: true
    k8sPodOwner: true
    kubeApiserverAvailability: true
    kubeApiserverBurnrate: true
    kubeApiserverHistogram: true
    kubeApiserverSlos: true
    kubeControllerManager: true
    kubelet: true
    kubeProxy: true
    kubePrometheusGeneral: true
    kubePrometheusNodeRecording: true
    kubernetesApps: true
    kubernetesResources: true
    kubernetesStorage: true
    kubernetesSystem: true
    kubeSchedulerAlerting: true
    kubeSchedulerRecording: true
    kubeStateMetrics: true
    network: true
    node: true
    nodeExporterAlerting: true
    nodeExporterRecording: true
    prometheus: true
    prometheusOperator: true
    windows: true
windowsMonitoring:
  enabled: {windows_monitoring}
grafana:
  enabled: {grafana}
kubernetesServiceMonitors:
  enabled: {kubernetes_service_monitors}
kubeApiServer:
  enabled: {kubernetes_api_server}
kubelet:
  enabled: {kubelet}
kubeControllerManager:
  enabled: {kube_controller_manager}
coreDns:
  enabled: {core_dns}
kubeEtcd:
  enabled: {kube_etcd}
kubeScheduler:
  enabled: {kube_scheduler}
kubeProxy:
  enabled: {kube_proxy}
kubeStateMetrics:
  enabled: {kube_state_metrics}
nodeExporter:
  enabled: {node_exporter}
prometheusOperator:
  enabled: {prometheus_operator}
prometheus:
  enabled: {prometheus}
"#,
    );
    HelmChartScore {
        namespace: Some(NonBlankString::from_str(&config.namespace).unwrap()),
        release_name: NonBlankString::from_str("kube-prometheus").unwrap(),
        chart_name: NonBlankString::from_str(
            "oci://ghcr.io/prometheus-community/charts/kube-prometheus-stack",
        )
        .unwrap(),
        chart_version: None,
        values_overrides: None,
        values_yaml: Some(values.to_string()),
        create_namespace: true,
        install_only: true,
        repository: None,
    }
}
    //    let alertmanager_config = alert_manager_yaml_builder(&config);
    //    values.push_str(&alertmanager_config);
    //
    //    fn alert_manager_yaml_builder(config: &KubePrometheusConfig) -> String {
    //        let mut receivers = String::new();
    //        let mut routes = String::new();
    //        let mut global_configs = String::new();
    //        let alert_manager = config.alert_manager;
    //        for alert_channel in &config.alert_channel {
    //            match alert_channel {
    //                AlertChannel::Discord { name, .. } => {
    //                    let (receiver, route) = discord_alert_builder(name);
    //                    info!("discord receiver: {} \nroute: {}", receiver, route);
    //                    receivers.push_str(&receiver);
    //                    routes.push_str(&route);
    //                }
    //                AlertChannel::Slack {
    //                    slack_channel,
    //                    webhook_url,
    //                } => {
    //                    let (receiver, route) = slack_alert_builder(slack_channel);
    //                    info!("slack receiver: {} \nroute: {}", receiver, route);
    //                    receivers.push_str(&receiver);
    //
    //                    routes.push_str(&route);
    //                    let global_config = format!(
    //                        r#"
    //    global:
    //      slack_api_url: {webhook_url}"#
    //                    );
    //
    //                    global_configs.push_str(&global_config);
    //                }
    //                AlertChannel::Smpt { .. } => todo!(),
    //            }
    //        }
    //        info!("after alert receiver: {}", receivers);
    //        info!("after alert routes: {}", routes);
    //
    //        let alertmanager_config = format!(
    //            r#"
    //alertmanager:
    //  enabled: {alert_manager}
    //  config: {global_configs}
    //    route:
    //      group_by: ['job']
    //      group_wait: 30s
    //      group_interval: 5m
    //      repeat_interval: 12h
    //      routes:
    //{routes}
    //    receivers:
    //    - name: 'null'
    //{receivers}"#
    //        );
    //
    //        info!("alert manager config: {}", alertmanager_config);
    //        alertmanager_config
    //    }



//fn discord_alert_builder(release_name: &String) -> (String, String) {
//    let discord_receiver_name = format!("Discord-{}", release_name);
//    let receiver = format!(
//        r#"
//    - name: '{discord_receiver_name}'
//      webhook_configs:
//      - url: 'http://{release_name}-alertmanager-discord:9094'
//        send_resolved: true"#,
//    );
//    let route = format!(
//        r#"
//      - receiver: '{discord_receiver_name}'
//        matchers: 
//          - alertname!=Watchdog
//        continue: true"#,
//    );
//    (receiver, route)
//}
//
//fn slack_alert_builder(slack_channel: &String) -> (String, String) {
//    let slack_receiver_name = format!("Slack-{}", slack_channel);
//    let receiver = format!(
//        r#"
//    - name: '{slack_receiver_name}'
//      slack_configs:
//      - channel: '{slack_channel}'
//        send_resolved: true
//        title: '{{{{ .CommonAnnotations.title }}}}'
//        text: '{{{{ .CommonAnnotations.description }}}}'"#,
//    );
//    let route = format!(
//        r#"
//      - receiver: '{slack_receiver_name}'
//        matchers: 
//          - alertname!=Watchdog
//        continue: true"#,
//    );
//    (receiver, route)
//}
