{ config, lib, pkgs, inputs, ... }:

let
  # this gets rid of the implicit dependency on ghc, reducing closure size
  stripLib = drv: pkgs.stdenv.mkDerivation {
    name = drv.name + "-without-lib";
    src = drv.outPath;
    buildPhase = ''
      mkdir -p $out
      cp -r $src/bin $out
    '';
    phases = [ "buildPhase" ];
  };
in
{
  services.nginx.recommendedProxySettings = true;
  services.nginx.virtualHosts."tracktrain.stuebinm.eu" = {
    locations."/" = {
      proxyPass = "http://192.168.42.41:4000";
      proxyWebsockets = true;
    };
    # don't expose prometheus endpoint
    locations."/metrics".return = "404";

    enableACME = true;
    forceSSL = true;
    extraConfig = ''
      add_header 'Access-Control-Allow-Origin' '*' always;
    '';
  };
  services.nginx.virtualHosts."tracktrain.ilztalbahn.eu" = {
    locations."/api" = {
      proxyPass = "http://192.168.42.41:4000";
      proxyWebsockets = true;
      extraConfig = ''
        add_header 'Access-Control-Allow-Origin' '*' always;
      '';
    };
    locations."/metrics/" = {
      proxyPass = "http://localhost:2342";
      proxyWebsockets = true;
      extraConfig = ''
        rewrite  ^/metrics/(.*)  /$1 break;
      '';
    };
    enableACME = true;
    forceSSL = true;
  };

  services.prometheus = {
    enable = true;
    port = 9001;
    scrapeConfigs = [ {
      job_name = "tracktrain";
      static_configs = [{
        targets = [  "192.168.42.41:4000" ];
      }];
    } ];
  };

  services.grafana = {
    enable = true;
    domain = "tracktrain.ilztalbahn.eu";
    rootUrl = "%(protocol)s://%(domain)s:/metrics/";
    port = 2342;
    addr = "0.0.0.0";
    extraOptions.serve_from_sub_path = "true";

    provision = {
      enable = true;
      datasources = [ {
        url = "http://localhost:9001";
        type = "prometheus";
        name = "prometheus";
      } ];
    };
  };

  networking.firewall.allowedTCPPorts = [ 443 ];

  containers.tracktrain = {
    autoStart = true;
    privateNetwork = true;
    hostAddress6 = "fd00::42:40";
    localAddress6 = "fd00::42:41";
    hostAddress = "192.168.42.40";
    localAddress = "192.168.42.41";

    config = { config, pkgs, ... }: {

      systemd.services.tracktrain = {
        enable = true;

        description = "tracks trains, hopefully";
        wantedBy = [ "multi-user.target" ];
        after = [ "network.target" ];
        serviceConfig.Type = "simple";
        path = [ pkgs.wget ];
        script = ''
          cd /tmp
          wget "https://ilztalbahn.eu/wp-content/uploads/2020/07/gtfs.zip"
          ${stripLib (((import inputs.tracktrain {nixpkgs = pkgs;}))
            # have to remove version constraints because some aren't in 22.05
            .overrideAttrs (old: { patchPhase = ''
              sed -i "s/base.*/base/g" *.cabal
              sed -i "s/^>=.*//g" *.cabal
              sed -i "s/>=.*//g" *.cabal
            ''; }))
           }/bin/tracktrain --dbString="dbname=tracktrain user=tracktrain" --warp.port=4000 +RTS -T
        '';
        startAt = "daily";
      };

      services.postgresql = {
        enable = true;

        ensureDatabases = [ "tracktrain" ];
        ensureUsers = [ {
          name = "tracktrain";
          ensurePermissions = {
            "DATABASE tracktrain" = "ALL PRIVILEGES";
          };
        } ];
        authentication = ''
          local   all   all                              trust
          host    all   all        127.0.0.1/32          trust
        '';
      };

      networking.firewall.allowedTCPPorts = [ 4000 ];
      system.stateVersion = "22.05";

      services.coredns = {
        enable = true;
        config = ''
          .:53 {
          forward . 1.1.1.1
          }
        '';
      };
    };
  };

  networking.nat = {
    enable = true;
    internalInterfaces = [ "ve-tracktrain" ];
    externalInterface = "ens3";
  };

}