{ config, lib, ... }:

let
  cfg = config.services.maubot;
  user = config.users.users.maubot;
  synapse = config.services.matrix-synapse;

  inherit (lib)
    concatLines
    mkEnableOption
    mkIf
    mkOption
    optionalString
    types
    ;
  inherit (builtins) toString listToAttrs;
in
{
  options.services.maubot = {
    admins = mkOption {
      type = types.listOf types.str;
      default = [ ];
      example = [
        "alice"
        "bob"
      ];
      description = "List of admin users for Maubot. Each admin must have a corresponding entry in the SOPS file under 'maubot/admins/<admin>' containing their password";
    };
    sops = mkEnableOption "SOPS integration";
  };

  config = mkIf cfg.enable {
    services.maubot = {
      extraConfigFile = mkIf cfg.sops config.sops.templates."maubot/extra-config-file".path;
      settings = {
        server = {
          port = 29316;
          public_url = synapse.settings.public_baseurl;
        };
        plugin_directories = with user; {
          upload = home + "/plugins";
          load = [ (home + "/plugins") ];
          trash = home + "/trash";
        };
        plugin_databases = with user; {
          sqlite = home + "/plugins";
        };
        # FIXME: ValueError: dictionary doesn't specify a version
        # logging = with user; {
        #   handlers.file.filename = home + "/maubot.log";
        # };
      };
    };

    environment.systemPackages = [
      cfg.package
    ];

    systemd.tmpfiles.rules = [
      "d ${cfg.dataDir} 0755 ${user.name} ${user.group} -"
      "d ${cfg.settings.plugin_directories.upload} 0755 ${user.name} ${user.group} -"
      "d ${cfg.settings.plugin_directories.trash} 0755 ${user.name} ${user.group} -"
    ];

    services.nginx.virtualHosts."${synapse.settings.server_name}".locations = {
      "^~ /_matrix/maubot/" = {
        proxyPass = with cfg.settings.server; "http://${hostname}:${toString port}";
        proxyWebsockets = true;
      };
      "^~ /_matrix/maubot/v1/logs" = {
        proxyPass = with cfg.settings.server; "http://${hostname}:${toString port}";
        proxyWebsockets = true;
      };
    };

    sops = mkIf cfg.sops (
      let
        owner = user.name;
        group = user.group;
        mode = "0400";
      in
      {
        secrets = listToAttrs (
          map (admin: {
            name = "maubot/admins/${admin}";
            value = { inherit owner group mode; };
          }) cfg.admins
        );
        templates."maubot/extra-config-file" = {
          inherit owner group mode;
          content = ''
            homeservers:
              ${synapse.settings.server_name}:
                url: http://127.0.0.1:${toString synapse.port}
                secret: ${config.sops.placeholder."matrix/registration-shared-secret"}
          ''
          + optionalString (cfg.admins != [ ]) (
            ''
              admins:
            ''
            + concatLines (
              map (admin: "  ${admin}: ${config.sops.placeholder."maubot/admins/${admin}"}") cfg.admins
            )
          );
        };
      }
    );
  };

}
