## `makeMakeDeployment` -- Function to help hosting providers make a
## `makeDeployment` function.
##
## https://factoryfactoryfactory.net/

## Generic utilities used in this function, eg. nixpkgs, NixOps4 providers, etc.
## REVIEW: We should maybe be more specific than just `inputs`.
{
  lib,
  nixops4,
  nixops4-nixos,
  fediversity,
}:

## Information on the hosting provider's infrastructure. This is where we inform
## this function of where it can find eg. Proxmox.
{
  ## Four NixOS configuration resource modules for four services. Those are VMs
  ## that are already deployed and on which we will push our configurations.
  ##
  ## - Ultimately, we just want a pool of VMs, or even just a Proxmox.
  ## - Each machine is flagged for a certain use case until we control DNS.
  garageConfigurationResource,
  mastodonConfigurationResource,
  peertubeConfigurationResource,
  pixelfedConfigurationResource,
}:

## From the hosting provider's perspective, the function is meant to be
## partially applied only until here.

## Information on the specific deployment that we request. This is the
## information coming from the FediPanel.
##
## FIXME: lock step the interface with the definitions in the FediPanel
panelConfig:

let
  inherit (lib) mkMerge mkIf;

in

## Regular arguments of a NixOps4 deployment module.
{ providers, ... }:

{
  providers = { inherit (nixops4.modules.nixops4Provider) local; };

  resources =
    let
      ## NOTE: All of these secrets are publicly available in this source file
      ## and will end up in the Nix store. We don't care as they are only ever
      ## used for testing anyway.
      ##
      ## FIXME: Generate and store in NixOps4's state.
      mastodonS3KeyConfig =
        { pkgs, ... }:
        {
          s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK3515373e4c851ebaad366558";
          s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7d37d093435a41f2aab8f13c19ba067d9776c90215f56614adad6ece597dbb34";
        };
      peertubeS3KeyConfig =
        { pkgs, ... }:
        {
          s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GK1f9feea9960f6f95ff404c9b";
          s3SecretKeyFile = pkgs.writeText "s3SecretKey" "7295c4201966a02c2c3d25b5cea4a5ff782966a2415e3a196f91924631191395";
        };
      pixelfedS3KeyConfig =
        { pkgs, ... }:
        {
          s3AccessKeyFile = pkgs.writeText "s3AccessKey" "GKb5615457d44214411e673b7b";
          s3SecretKeyFile = pkgs.writeText "s3SecretKey" "5be6799a88ca9b9d813d1a806b64f15efa49482dbe15339ddfaf7f19cf434987";
        };

      makeConfigurationResource = resourceModule: config: {
        type = providers.local.exec;
        imports = [
          nixops4-nixos.modules.nixops4Resource.nixos
          resourceModule

          {
            ## NOTE: With NixOps4, there are several levels and all of them live
            ## in the NixOS module system:
            ##
            ##   1. Each NixOps4 deployment is a module.
            ##   2. Each NixOps4 resource is a module. This very comment is
            ##      inside an attrset imported as a module in a resource.
            ##   3. Each NixOps4 'configuration' resource contains an attribute
            ##      'nixos.module', itself a NixOS configuration module.
            nixos.module =
              { ... }:
              {
                imports = [
                  config
                  fediversity
                ];
              };
          }
        ];
      };

    in

    mkMerge [

      (mkIf (panelConfig.mastodon.enable || panelConfig.peertube.enable || panelConfig.pixelfed.enable) {
        garage-configuration = makeConfigurationResource garageConfigurationResource (
          { pkgs, ... }:
          {
            fediversity = {
              inherit (panelConfig) domain;
              garage.enable = true;
              pixelfed = pixelfedS3KeyConfig { inherit pkgs; };
              mastodon = mastodonS3KeyConfig { inherit pkgs; };
              peertube = peertubeS3KeyConfig { inherit pkgs; };
            };
          }
        );
      })

      (mkIf panelConfig.mastodon.enable {
        mastodon-configuration = makeConfigurationResource mastodonConfigurationResource (
          { pkgs, ... }:
          {
            fediversity = {
              inherit (panelConfig) domain;
              temp.initialUser = {
                inherit (panelConfig.initialUser) username email displayName;
                # FIXME: disgusting, but nvm, this is going to be replaced by
                # proper central authentication at some point
                passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
              };

              mastodon = mastodonS3KeyConfig { inherit pkgs; } // {
                enable = true;
              };

              temp.cores = 1; # FIXME: should come from NixOps4 eventually
            };
          }
        );
      })

      (mkIf panelConfig.peertube.enable {
        peertube-configuration = makeConfigurationResource peertubeConfigurationResource (
          { pkgs, ... }:
          {
            fediversity = {
              inherit (panelConfig) domain;
              temp.initialUser = {
                inherit (panelConfig.initialUser) username email displayName;
                # FIXME: disgusting, but nvm, this is going to be replaced by
                # proper central authentication at some point
                passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
              };

              peertube = peertubeS3KeyConfig { inherit pkgs; } // {
                enable = true;
                ## NOTE: Only ever used for testing anyway.
                ##
                ## FIXME: Generate and store in NixOps4's state.
                secretsFile = pkgs.writeText "secret" "574e093907d1157ac0f8e760a6deb1035402003af5763135bae9cbd6abe32b24";
              };
            };
          }
        );
      })

      (mkIf panelConfig.pixelfed.enable {
        pixelfed-configuration = makeConfigurationResource pixelfedConfigurationResource (
          { pkgs, ... }:
          {
            fediversity = {
              inherit (panelConfig) domain;
              temp.initialUser = {
                inherit (panelConfig.initialUser) username email displayName;
                # FIXME: disgusting, but nvm, this is going to be replaced by
                # proper central authentication at some point
                passwordFile = pkgs.writeText "password" panelConfig.initialUser.password;
              };

              pixelfed = pixelfedS3KeyConfig { inherit pkgs; } // {
                enable = true;
              };
            };
          }
        );
      })
    ];
}