{
  config,
  pkgs,
  lib,
  ...
}:
let
  inherit (lib)
    concatStringsSep
    mapAttrsToList
    mkDefault
    mkEnableOption
    mkIf
    mkOption
    mkPackageOption
    optionalString
    types
    ;
  inherit (pkgs) writeShellApplication;

  # TODO: configure the name globally for everywhere it's used
  name = "panel";

  cfg = config.services.${name};

  database-url = "sqlite:////var/lib/${name}/db.sqlite3";

  python-environment = pkgs.python3.withPackages (
    ps:
    with ps;
    [
      uvicorn
      cfg.package
      dj-database-url
      django-compressor
      django-debug-toolbar
      django-libsass
      django_4
      setuptools
    ]
    ++ cfg.package.propagatedBuildInputs
  );

  configFile = pkgs.concatText "configuration.py" [
    ((pkgs.formats.pythonVars { }).generate "settings.py" cfg.settings)
    (builtins.toFile "extra-settings.py" cfg.extra-settings)
  ];

  manage-service = writeShellApplication {
    name = "manage";
    text = ''exec ${cfg.package}/bin/manage.py "$@"'';
  };

  manage-admin = writeShellApplication {
    # This allows running the `manage` command in the system environment, e.g. to initialise an admin user
    # Executing
    name = "manage";
    text =
      ''
        systemd-run --pty \
          --same-dir \
          --wait \
          --collect \
          --service-type=exec \
          --unit "manage-${name}.service" \
          --property "User=${name}" \
          --property "Group=${name}" \
          --property "Environment=DATABASE_URL=${database-url} USER_SETTINGS_FILE=${configFile}" \
      ''
      + optionalString (credentials != [ ]) (
        (concatStringsSep " \\\n" (map (cred: "--property 'LoadCredential=${cred}'") credentials)) + " \\\n"
      )
      + ''
        ${lib.getExe manage-service} "$@"
      '';
  };

  credentials = mapAttrsToList (name: secretPath: "${name}:${secretPath}") cfg.secrets;
in
# TODO: for a more clever and generic way of running Django services:
#       https://git.dgnum.eu/mdebray/djangonix/
#       unlicensed at the time of writing, but surely worth taking some inspiration from...
{
  options.services.${name} = {
    enable = mkEnableOption "Service configuration for `${name}`";
    # NOTE: this requires that the package is present in `pkgs`
    package = mkPackageOption pkgs name { };
    production = mkOption {
      type = types.bool;
      default = true;
    };
    restart = mkOption {
      description = "systemd restart behavior";
      type = types.enum [
        "no"
        "on-success"
        "on-failure"
        "on-abnormal"
        "on-abort"
        "always"
      ];
      default = "always";
    };
    domain = mkOption { type = types.str; };
    host = mkOption {
      type = types.str;
      default = "127.0.0.1";
    };
    port = mkOption {
      type = types.port;
      default = 8000;
    };
    settings = mkOption {
      type = types.attrsOf types.anything;
      default = {
        STATIC_ROOT = mkDefault "/var/lib/${name}/static";
        DEBUG = mkDefault false;
        ALLOWED_HOSTS = mkDefault [
          cfg.domain
          cfg.host
          "localhost"
          "[::1]"
        ];
        CSRF_TRUSTED_ORIGINS = mkDefault [ "https://${cfg.domain}" ];
        COMPRESS_OFFLINE = true;
        LIBSASS_OUTPUT_STYLE = "compressed";
      };
      description = ''
        Django configuration as an attribute set.
        Name-value pairs will be converted to Python variable assignments.
      '';
    };
    extra-settings = mkOption {
      type = types.lines;
      default = "";
      description = ''
        Django configuration written in Python verbatim.
        Contents will be appended to the definitions in `settings`.
      '';
    };
    secrets = mkOption {
      type = types.attrsOf types.path;
      default = { };
    };
  };

  config = mkIf cfg.enable {
    environment.systemPackages = [ manage-admin ];

    services = {
      nginx.enable = true;
      nginx.virtualHosts = {
        ${cfg.domain} =
          {
            locations = {
              "/".proxyPass = "http://localhost:${toString cfg.port}";
              "/static/".alias = "/var/lib/${name}/static/";
            };
          }
          // lib.optionalAttrs cfg.production {
            enableACME = true;
            forceSSL = true;
          };
      };
    };

    users.users.${name} = {
      isSystemUser = true;
      group = name;
    };

    users.groups.${name} = { };
    systemd.services.${name} = {
      description = "${name} ASGI server";
      after = [ "network.target" ];
      wantedBy = [ "multi-user.target" ];
      path = [
        python-environment
        manage-service
      ];
      preStart = ''
        # Auto-migrate on first run or if the package has changed
        versionFile="/var/lib/${name}/package-version"
        if [[ $(cat "$versionFile" 2>/dev/null) != ${cfg.package} ]]; then
          manage migrate --no-input
          manage collectstatic --no-input --clear
          manage compress --force
          echo ${cfg.package} > "$versionFile"
        fi
      '';
      script = ''
        export PYTHONPATH=$PYTHONPATH:${cfg.package}/lib/python3.12/site-packages
        ${python-environment}/bin/python -m uvicorn ${name}.asgi:application --host ${cfg.host} --port ${toString cfg.port}
      '';
      serviceConfig = {
        Restart = "always";
        User = name;
        WorkingDirectory = "/var/lib/${name}";
        StateDirectory = name;
        RuntimeDirectory = name;
        LogsDirectory = name;
      } // lib.optionalAttrs (credentials != [ ]) { LoadCredential = credentials; };
      environment = {
        USER_SETTINGS_FILE = "${configFile}";
        DATABASE_URL = database-url;
      };
    };

    networking.firewall.allowedTCPPorts = [
      80
      443
    ];
  };
}