{ config, pkgs, lib, ... }:
let
  serverCfg = config.syscfg.server;
  builder = import ./builder.nix { inherit config lib pkgs serverCfg; };
  loadApp = name: containerCfg:
    builder.mkApp name ((import (./apps + "/${name}.nix")) {
      inherit config pkgs lib containerCfg builder name;
    });
  loadedContainers = lib.mapAttrs loadApp serverCfg.containers;
  appsList = builtins.attrValues loadedContainers;
  concatRuntimeLists = field: lib.concatMap (app: app.runtime.${field}) appsList;
  mkNamedUnits = mkUnit: items: lib.listToAttrs (map mkUnit items);
  mergedContainers = lib.concatMapAttrs (appName: app:
    lib.mapAttrs' (cName: cCfg: lib.nameValuePair "${appName}-${cName}" cCfg) app.runtime.containers
  ) loadedContainers;
  basePathConfigs =
    lib.mapAttrsToList (_: cfg: cfg) (lib.filterAttrs (name: _: name != "config" && name != "data") serverCfg.path);
  runtimePathConfigs = concatRuntimeLists "paths";
  allSetupConfigs = map (app: ({ name = app.name; envFile = ""; } // app.runtime.setup)) appsList;
  allCronsConfigs = concatRuntimeLists "cron";
  allVMConfigs = builtins.filter (app: app.runtime.vm != null) appsList;
  mkPathSetup = cfg:
    let
      effectiveCfg = {
        owner = "root:root";
        mode = "0755";
        dirs = [];
      } // cfg;
    in ''
      ${pkgs.coreutils}/bin/mkdir -p "${effectiveCfg.path}"
      ${lib.concatMapStringsSep "\n" (dir: "${pkgs.coreutils}/bin/mkdir -p ${effectiveCfg.path}/${lib.escapeShellArg dir}") effectiveCfg.dirs}
      ${pkgs.coreutils}/bin/chown -R ${effectiveCfg.owner} "${effectiveCfg.path}"
      ${pkgs.coreutils}/bin/chmod -R ${effectiveCfg.mode} "${effectiveCfg.path}"
    '';
in {
  config = lib.mkMerge [{
    syscfg.server.loadedContainers = loadedContainers;
  } (lib.mkIf (loadedContainers != {}) {
      virtualisation.oci-containers = {
        backend = "podman";
        containers = mergedContainers;
      };
      system.activationScripts.container-setup-base-dirs = {
        deps = [ "users" "groups" ];
        text = lib.concatStringsSep "\n" (map mkPathSetup basePathConfigs);
      };
      system.activationScripts.container-setup-runtime-dirs = {
        deps = [ "container-setup-base-dirs" ];
        text = lib.concatStringsSep "\n" (map mkPathSetup runtimePathConfigs);
      };

      systemd.services = {
        podman-gc = {
          description = "Podman garbage collection";
          serviceConfig.Type = "oneshot";
          script = ''
            ${pkgs.podman}/bin/podman container prune -f
            ${pkgs.podman}/bin/podman image prune -f
            ${pkgs.podman}/bin/podman system prune -a --volumes -f
          '';
          startAt = "weekly";
        };
      } 
      // mkNamedUnits (e: {
        name = "${e.name}-vm";
        value = {
          description = "Isolated NixOS Guest VM for ${e.name}";
          after = [ "network-online.target" ];
          wants = [ "network-online.target" ];
          wantedBy = [ "multi-user.target" ];
          environment = {
            QEMU_VM_REG_SND = "0";
            NIX_DISK_IMAGE = "/media/data/kvm/${e.name}-guest.qcw2";
          };
          serviceConfig = {
            Type = "simple";
            Restart = "always";
            RestartSec = "10s";
            ExecStartPre = "${pkgs.coreutils}/bin/mkdir -p /media/data/kvm";
            ExecStart = ''
              ${builder.mkVm { name = e.name; vm = e.runtime.vm; }}/bin/run-${e.name}-vm -nographic
            '';
          };
        };
      }) allVMConfigs
       // mkNamedUnits (e: {
        name = "${e.name}-setup";
        value = {
          description = "Run ${e.name} setup";
          after = [ "podman-${e.name}-${e.trigger}.service" ];
          wants = [ "podman-${e.name}-${e.trigger}.service" ];
          partOf = [ "podman-${e.name}-${e.trigger}.service" ];
          wantedBy = [ "multi-user.target" ];
          restartTriggers = [ e.script ];
          serviceConfig = {
            Type = "simple";
            Restart = "on-failure";
            RestartSec = "15s";
            TimeoutStartSec = "360s";
            EnvironmentFile = e.envFile;
            ExecStart = e.script;
            RemainAfterExit = true;
            User = "root";
          };
        };
      }) allSetupConfigs;

      services.cron = {
        enable = true;
        systemCronJobs = allCronsConfigs;
      };
  })];
}
