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

with pkgs;

# NOTE Reference the environment variable set in the corresponding agenix secret
let
  database = {
    connection_string = "$DB_STRING";
    max_open_conns = 100;
    max_idle_conns = 5;
    conn_max_lifetime = -1;
  };

in {
  # Matrix server configuration
  services.dendrite = {
    enable = true;
    httpPort = 8008;
    environmentFile = config.age.secrets.dendrite-postgres.path;
    loadCredential = [ "private_key:${config.age.secrets.dendrite.path}" ];
    settings = {
      global = {
        server_name = "coolneng.duckdns.org";
        private_key = config.age.secrets.dendrite.path;
        inherit database;
        dns_cache.enabled = true;
      };
      # HACK Inherit postgres connection string for the rest of the DBs
      app_service_api = {
        inherit database;
        config_files = [
          "/var/lib/matrix-as-facebook/facebook-registration.yaml"
          "/var/lib/matrix-as-signal/signal-registration.yaml"
          "/var/lib/matrix-as-telegram/telegram-registration.yaml"
        ];
      };
      media_api = { inherit database; };
      room_server = { inherit database; };
      push_server = { inherit database; };
      mscs = {
        inherit database;
        mscs = [ "msc2836" "msc2946" ];
      };
      sync_api = { inherit database; };
      key_server = { inherit database; };
      federation_api = { inherit database; };
      user_api = {
        account_database = database;
        device_database = database;
      };
    };
  };

  # Start dendrite after config files are mounted
  systemd.services.dendrite.unitConfig.RequiresMountsFor = [
    /var/lib/matrix-as-facebook
    /var/lib/matrix-as-signal
    /var/lib/matrix-as-telegram
  ];

  # Matrix bridges
  services.matrix-appservices = {
    homeserver = "dendrite";
    homeserverDomain = "coolneng.duckdns.org";
    homeserverURL = "https://matrix.coolneng.duckdns.org";
    services = {
      telegram = {
        port = 8118;
        format = "mautrix-python";
        package = mautrix-telegram;
        serviceConfig.EnvironmentFile = config.age.secrets.telegram.path;
        settings = {
          appservice.database = "$DB_STRING";
          homeserver.software = "standard";
          telegram = {
            api_id = "$API_ID";
            api_hash = "$API_HASH";
          };
          bridge = {
            permissions."@coolneng:coolneng.duckdns.org" = "admin";
            backfill.normal_groups = true;
          };
        };
      };
      facebook = {
        port = 8228;
        format = "mautrix-python";
        package = mautrix-facebook;
        serviceConfig.EnvironmentFile = config.age.secrets.facebook.path;
        settings = {
          appservice.database = "$DB_STRING";
          homeserver.software = "standard";
          bridge.permissions."@coolneng:coolneng.duckdns.org" = "admin";
        };
      };
      signal = {
        port = 8338;
        format = "mautrix-python";
        package = mautrix-signal;
        serviceConfig = {
          EnvironmentFile = config.age.secrets.signal.path;
          StateDirectory = [ "matrix-as-signal" "signald" ];
          JoinNamespaceOf = "signald.service";
          SupplementaryGroups = [ "signald" ];
        };
        settings = {
          appservice.database = "$DB_STRING";
          homeserver.software = "standard";
          bridge.permissions."@coolneng:coolneng.duckdns.org" = "admin";
          signal = {
            socket_path = config.services.signald.socketPath;
            outgoing_attachment_dir = "/var/lib/signald/tmp";
          };
        };
      };
    };
  };

  # Additional settings for mautrix-signal
  services.signald = {
    enable = true;
    user = "matrix-as-signal";
  };
  systemd.services.matrix-as-signal = {
    requires = [ "signald.service" ];
    after = [ "signald.service" ];
    unitConfig.JoinsNamespaceOf = "signald.service";
    path = [ ffmpeg ];
  };

  # Enable voice messages for facebook
  systemd.services.matrix-as-facebook.path = [ ffmpeg ];

  # MQTT configuration
  services.mosquitto = {
    enable = true;
    dataDir = "/vault/mosquitto";
    logType = [ "websockets" "error" "warning" "notice" "information" ];
    logDest = [ "syslog" ];
    listeners = [{
      users.homeostasis = {
        acl = [ "write #" ];
        hashedPasswordFile = config.age.secrets.mqtt-sender.path;
      };
      users.prometheus = {
        acl = [ "read #" ];
        hashedPasswordFile = config.age.secrets.mqtt-receiver.path;
      };
    }];
  };

}