{ config, pkgs, modulesPath, sops, ... }:
let
  matrixDomain = "matrix2.swarsel.win";
in
{


  services = {
    xserver.xkb = {
      layout = "us";
      variant = "altgr-intl";
    };
    openssh = {
      enable = true;
      settings.PermitRootLogin = "yes";
      listenAddresses = [{
        port = 22;
        addr = "0.0.0.0";
      }];
    };
  };

  nix.settings.experimental-features = [ "nix-command" "flakes" ];

  proxmoxLXC = {
    manageNetwork = true; # manage network myself
    manageHostName = false; # manage hostname myself
  };

  networking = {
    useDHCP = true;
    enableIPv6 = false;
  };

  users.users.root.openssh.authorizedKeys.keyFiles = [
    ../../../secrets/keys/authorized_keys
  ];

  system.stateVersion = "23.05"; # TEMPLATE - but probably no need to change

  environment.shellAliases = {
    nswitch = "cd /.dotfiles; git pull; nixos-rebuild --flake .#$(hostname) switch; cd -;";
  };


  imports = [
    (modulesPath + "/virtualisation/proxmox-lxc.nix")
    ./hardware-configuration.nix
    # we import here a service that is not available yet on normal nixpkgs
    # this module is hence not in the modules list, we add it ourselves
  ];

  networking = {
    hostName = "matrix"; # Define your hostname.
    firewall.enable = false;
  };
  environment.systemPackages = with pkgs; [
    git
    gnupg
    ssh-to-age
    matrix-synapse
    lottieconverter
    ffmpeg
  ];

  sops = {
    age.sshKeyPaths = [ "/etc/ssh/sops" ];
    defaultSopsFile = "/.dotfiles/secrets/matrix/secrets.yaml";
    validateSopsFiles = false;
    secrets = {
      matrixsharedsecret = { owner = "matrix-synapse"; };
      mautrixtelegram_as = { owner = "matrix-synapse"; };
      mautrixtelegram_hs = { owner = "matrix-synapse"; };
      mautrixtelegram_api_id = { owner = "matrix-synapse"; };
      mautrixtelegram_api_hash = { owner = "matrix-synapse"; };
    };
    templates = {
      "matrix_user_register.sh".content = ''
        register_new_matrix_user -k ${config.sops.placeholder.matrixsharedsecret} http://localhost:8008
      '';
      matrixshared = {
        owner = "matrix-synapse";
        content = ''
          registration_shared_secret: ${config.sops.placeholder.matrixsharedsecret}
        '';
      };
      mautrixtelegram = {
        owner = "matrix-synapse";
        content = ''
          MAUTRIX_TELEGRAM_APPSERVICE_AS_TOKEN=${config.sops.placeholder.mautrixtelegram_as}
          MAUTRIX_TELEGRAM_APPSERVICE_HS_TOKEN=${config.sops.placeholder.mautrixtelegram_hs}
          MAUTRIX_TELEGRAM_TELEGRAM_API_ID=${config.sops.placeholder.mautrixtelegram_api_id}
          MAUTRIX_TELEGRAM_TELEGRAM_API_HASH=${config.sops.placeholder.mautrixtelegram_api_hash}
        '';
      };
    };
  };

  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";
      CREATE ROLE "mautrix-telegram" WITH LOGIN PASSWORD 'telegram';
      CREATE DATABASE "mautrix-telegram" WITH OWNER "mautrix-telegram"
        TEMPLATE template0
        LC_COLLATE = "C"
        LC_CTYPE = "C";
      CREATE ROLE "mautrix-whatsapp" WITH LOGIN PASSWORD 'whatsapp';
      CREATE DATABASE "mautrix-whatsapp" WITH OWNER "mautrix-whatsapp"
        TEMPLATE template0
        LC_COLLATE = "C"
        LC_CTYPE = "C";
      CREATE ROLE "mautrix-signal" WITH LOGIN PASSWORD 'signal';
      CREATE DATABASE "mautrix-signal" WITH OWNER "mautrix-signal"
        TEMPLATE template0
        LC_COLLATE = "C"
        LC_CTYPE = "C";
    '';
  };

  services.matrix-synapse = {
    enable = true;
    settings = {
      app_service_config_files = [
        "/var/lib/matrix-synapse/telegram-registration.yaml"
        "/var/lib/matrix-synapse/whatsapp-registration.yaml"
        "/var/lib/matrix-synapse/signal-registration.yaml"
        "/var/lib/matrix-synapse/doublepuppet.yaml"
      ];
      server_name = matrixDomain;
      public_baseurl = "https://${matrixDomain}";
      listeners = [
        {
          port = 8008;
          bind_addresses = [ "0.0.0.0" ];
          type = "http";
          tls = false;
          x_forwarded = true;
          resources = [
            {
              names = [ "client" "federation" ];
              compress = true;
            }
          ];
        }
      ];
    };
    extraConfigFiles = [
      config.sops.templates.matrixshared.path
    ];
  };

  services.mautrix-telegram = {
    enable = true;
    environmentFile = config.sops.templates.mautrixtelegram.path;
    settings = {
      homeserver = {
        address = "http://localhost:8008";
        domain = matrixDomain;
      };
      appservice = {
        address = "http://localhost:29317";
        hostname = "0.0.0.0";
        port = "29317";
        provisioning.enabled = true;
        id = "telegram";
        # ephemeral_events = true; # not needed due to double puppeting
        public = {
          enabled = false;
        };
        database = "postgresql:///mautrix-telegram?host=/run/postgresql";
      };
      bridge = {
        relaybot.authless_portals = true;
        allow_avatar_remove = true;
        allow_contact_info = true;
        sync_channel_members = true;
        startup_sync = true;
        sync_create_limit = 0;
        sync_direct_chats = true;
        telegram_link_preview = true;
        permissions = {
          "*" = "relaybot";
          "@swarsel:${matrixDomain}" = "admin";
        };
        animated_sticker = {
          target = "gif";
          args = {
            width = 256;
            height = 256;
            fps = 30; # only for webm
            background = "020202"; # only for gif, transparency not supported
          };
        };
      };
    };
  };
  systemd.services.mautrix-telegram.path = with pkgs; [
    lottieconverter # for animated stickers conversion, unfree package
    ffmpeg # if converting animated stickers to webm (very slow!)
  ];

  services.mautrix-whatsapp = {
    enable = true;
    settings = {
      homeserver = {
        address = "http://localhost:8008";
        domain = matrixDomain;
      };
      appservice = {
        address = "http://localhost:29318";
        hostname = "0.0.0.0";
        port = 29318;
        database = {
          type = "postgres";
          uri = "postgresql:///mautrix-whatsapp?host=/run/postgresql";
        };
      };
      bridge = {
        displayname_template = "{{or .FullName .PushName .JID}} (WA)";
        history_sync = {
          backfill = true;
          max_initial_conversations = -1;
          message_count = -1;
          request_full_sync = true;
          full_sync_config = {
            days_limit = 900;
            size_mb_limit = 5000;
            storage_quota_mb = 5000;
          };
        };
        login_shared_secret_map = {
          matrixDomain = "as_token:doublepuppet";
        };
        sync_manual_marked_unread = true;
        send_presence_on_typing = true;
        parallel_member_sync = true;
        url_previews = true;
        caption_in_message = true;
        extev_polls = true;
        permissions = {
          "*" = "relaybot";
          "@swarsel:${matrixDomain}" = "admin";
        };
      };
    };
  };

  services.mautrix-signal = {
    enable = true;
    settings = {
      homeserver = {
        address = "http://localhost:8008";
        domain = matrixDomain;
      };
      appservice = {

        address = "http://localhost:29328";
        hostname = "0.0.0.0";
        port = 29328;
        database = {
          type = "postgres";
          uri = "postgresql:///mautrix-signal?host=/run/postgresql";
        };
      };
      bridge = {
        displayname_template = "{{or .ContactName .ProfileName .PhoneNumber}} (Signal)";
        login_shared_secret_map = {
          matrixDomain = "as_token:doublepuppet";
        };
        caption_in_message = true;
        permissions = {
          "*" = "relaybot";
          "@swarsel:${matrixDomain}" = "admin";
        };
      };
    };
  };

  # restart the bridges daily. this is done for the signal bridge mainly which stops carrying
  # messages out after a while.

  systemd.timers."restart-bridges" = {
    wantedBy = [ "timers.target" ];
    timerConfig = {
      OnBootSec = "1d";
      OnUnitActiveSec = "1d";
      Unit = "restart-bridges.service";
    };
  };

  systemd.services."restart-bridges" = {
    script = ''
      systemctl restart mautrix-whatsapp.service
      systemctl restart mautrix-signal.service
      systemctl restart mautrix-telegram.service
    '';
    serviceConfig = {
      Type = "oneshot";
      User = "root";
    };
  };

}
