{
  config,
  lib,
  pkgs,
  ...
}:
let
  cfg = config.services.matrix-synapse;
  baseUrl = "https://${cfg.settings.server_name}";

  baseClientConfig = {
    "m.homeserver".base_url = baseUrl;
    "m.identity_server".base_url = "https://vector.im";
  };

  livekitConfig = optionalAttrs config.services.livekit.enable {
    "org.matrix.msc3575.proxy".url = baseUrl;
    "org.matrix.msc4143.rtc_foci" = [
      {
        type = "livekit";
        livekit_service_url = baseUrl + "/livekit/jwt";
      }
    ];
  };

  clientConfig = baseClientConfig // livekitConfig;

  serverConfig."m.server" = "${cfg.settings.server_name}:443";

  mkWellKnown = data: ''
    default_type application/json;
    add_header Access-Control-Allow-Origin *;
    return 200 '${builtins.toJSON data}';
  '';

  inherit (lib)
    mkEnableOption
    mkIf
    mkMerge
    mkOption
    optionalAttrs
    types
    ;
in
{
  imports = [
    ./bridges.nix
    ./livekit.nix
  ];

  options.services.matrix-synapse = {
    port = mkOption {
      type = types.nullOr types.port;
      default = 8008;
      description = ''
        The port to listen for HTTP(S) requests on (will be applied to a listener).
      '';
    };
    coturn = {
      enable = mkEnableOption "Coturn integration for Matrix Synapse.";
      realm = mkOption {
        type = types.str;
        default = "turn.${config.networking.domain}";
        description = "Realm for the coturn server used by Matrix Synapse.";
      };
      listening-port = mkOption {
        type = types.port;
        default = 3478;
      };
      tls-listening-port = mkOption {
        type = types.port;
        default = 5349;
      };
      alt-listening-port = mkOption {
        type = types.port;
        default = 3479;
      };
      alt-tls-listening-port = mkOption {
        type = types.port;
        default = 5350;
      };
    };
    sops = mkEnableOption "SOPS integration";
  };

  config = mkIf cfg.enable {
    services.postgresql = {
      enable = true;
      initialScript = pkgs.writeText "synapse-init.sql" ''
        CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
        CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
          TEMPLATE template0
          LC_COLLATE = 'C'
          LC_CTYPE = 'C';
      '';
    };

    services.matrix-synapse = mkMerge [
      {
        settings = {
          registration_shared_secret_path =
            mkIf cfg.sops
              config.sops.secrets."matrix/registration-shared-secret".path;
          server_name = config.networking.domain;
          public_baseurl = baseUrl;
          listeners = [
            {
              inherit (cfg) port;
              bind_addresses = [ "127.0.0.1" ];
              resources = [
                {
                  compress = true;
                  names = [ "client" ];
                }
                {
                  compress = false;
                  names = [ "federation" ];
                }
              ];
              tls = false;
              type = "http";
              x_forwarded = true;
            }
          ];
        };
      }
      (mkIf cfg.coturn.enable {
        settings = {
          turn_uris = with cfg.coturn; [
            "turn:${realm}:${toString listening-port}?transport=udp"
            "turn:${realm}:${toString listening-port}?transport=tcp"
            "turn:${realm}:${toString tls-listening-port}?transport=udp"
            "turn:${realm}:${toString tls-listening-port}?transport=tcp"
            "turn:${realm}:${toString alt-listening-port}?transport=udp"
            "turn:${realm}:${toString alt-listening-port}?transport=tcp"
            "turn:${realm}:${toString alt-tls-listening-port}?transport=udp"
            "turn:${realm}:${toString alt-tls-listening-port}?transport=tcp"
          ];
          extraConfigFiles = mkIf cfg.sops [ config.sops.templates."coturn/static-auth-secret.env".path ];
          turn_user_lifetime = "1h";
        };
      })
    ];

    environment.shellAliases = mkIf cfg.sops {
      register_new_matrix_user = "${cfg.package}/bin/register_new_matrix_user -k $(sudo cat ${cfg.settings.registration_shared_secret_path})";
    };

    services.nginx.virtualHosts."${cfg.settings.server_name}" = {
      enableACME = true;
      forceSSL = true;

      locations."= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
      locations."= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;

      locations."/_matrix".proxyPass = "http://127.0.0.1:${toString cfg.port}";
      locations."/_synapse".proxyPass = "http://127.0.0.1:${toString cfg.port}";
    };

    sops = mkIf cfg.sops {
      secrets = mkMerge [
        {
          "matrix/registration-shared-secret" = {
            owner = "matrix-synapse";
            group = "matrix-synapse";
            mode = "0400";
          };
        }
        (mkIf cfg.coturn.enable {
          "coturn/static-auth-secret" = {
            owner = "turnserver";
            group = "turnserver";
            mode = "0400";
          };
        })
      ];
      templates = mkIf cfg.coturn.enable {
        "coturn/static-auth-secret.env" = {
          owner = "matrix-synapse";
          group = "matrix-synapse";
          mode = "0400";
          content = ''
            static-auth-secret=${config.sops.placeholder."coturn/static-auth-secret"}
          '';
        };
      };
    };
  };
}
