{ config, pkgs, ... }:

{
  microvm.mem = 4096;
  c3d2.deployment.server = "server10";

  environment.systemPackages = with pkgs; [ influxdb ];

  networking = {
    firewall = {
      # influxdb
      allowedTCPPorts = [ 8086 ];
      # collectd
      allowedUDPPorts = [ 25826 ];
    };
    hostName = "grafana";
  };

  services = {
    grafana = {
      enable = true;

      provision = {
        enable = true;
        # curl https://root:SECRET@grafana.hq.c3d2.de/api/datasources | jq > hosts/grafana/datasources.json
        datasources.settings.datasources = map
          (datasource: {
            inherit (datasource) name type access orgId url password user database isDefault jsonData;
          })
          (with builtins; fromJSON (readFile ./datasources.json));
        dashboards.settings.providers = [{
          settings = {
            apiVersion = 1;
            providers = [{
              name = "c3d2";
            }];
          };
          # for id in `curl https://root:SECRET@grafana.hq.c3d2.de/api/search | jq -j 'map(.uid) | join(" ")'`; do curl https://root:SECRET@grafana.hq.c3d2.de/api/dashboards/uid/$id | jq .dashboard > hosts/grafana/dashboards/$id.json;done
          options.path = ./dashboards;
        }];
      };

      settings = {
        analytics.reporting_enabled = false;
        "auth.generic_oauth" = {
          enabled = true;
          allow_assign_grafana_admin = true;
          allow_sign_up = true;
          api_url = "https://auth.c3d2.de/dex/userinfo";
          auth_url = "https://auth.c3d2.de/dex/auth";
          client_id = "grafana";
          client_secret = "$__file{${config.sops.secrets."grafana/client-secret".path}}";
          disable_login_form = true; # only allow OAuth
          icon = "signin";
          name = "auth.c3d2.de";
          oauth_auto_login = true; # redirect automatically to the only oauth provider
          role_attribute_path = "contains(groups[*], 'grafana-admins') && 'Admin'";
          # https://dexidp.io/docs/custom-scopes-claims-clients/
          scopes = "openid email groups profile offline_access";
          token_url = "https://auth.c3d2.de/dex/token";
        };
        security = {
          admin_password = "$__file{${config.sops.secrets."grafana/admin-password".path}}";
          secret_key = "$__file{${config.sops.secrets."grafana/secret-key".path}}";
        };
        server.domain = "grafana.hq.c3d2.de";
        users.allow_sign_up = false;
      };
    };
    influxdb =
      let
        collectdTypes = pkgs.runCommand "collectd-types" { } ''
          mkdir -p $out/share/collectd
          cat ${pkgs.collectd-data}/share/collectd/types.db >> $out/share/collectd/types.db
          echo "stations  value:GAUGE:0:U" >> $out/share/collectd/types.db
        '';
      in
      {
        enable = true;
        extraConfig = {
          logging.level = "debug";
          collectd = [{
            enabled = true;
            database = "collectd";
            typesdb = "${collectdTypes}/share/collectd/types.db";
            # create retention policy "30d" on collectd duration 30d replication 1 default
            retention-policy = "30d";
          }];
        };
      };
    nginx = {
      enable = true;
      virtualHosts = {
        "grafana.hq.c3d2.de" = {
          default = true;
          enableACME = true;
          forceSSL = true;
          locations = { "/".proxyPass = "http://localhost:3000/"; };
        };
      };
    };
  };

  sops = {
    defaultSopsFile = ./secrets.yaml;
    secrets = let
      grafanaUser = {
        group = config.systemd.services.grafana.serviceConfig.User;
        owner = config.systemd.services.grafana.serviceConfig.User;
      };
    in {
      "grafana/admin-password" = grafanaUser;
      "grafana/client-secret" = grafanaUser;
      "grafana/secret-key" = grafanaUser;
    };
  };

  systemd.services =
    builtins.foldl'
      (services: service:
        services // {
          "${service}".serviceConfig = {
            RestartSec = 60;
            Restart = "always";
          };
        }
      )
      { } [ "grafana" "influxdb" ]
    // {
      # work around our slow storage that can't keep up
      influxdb.serviceConfig.LimitNOFILE = "1048576:1048576";
      influxdb.serviceConfig.TimeoutStartSec = "infinity";
    };

  system.stateVersion = "22.05";
}
