{ config, lib, ... }:
let
  userType = lib.types.submodule {
    options = {
      fullName = lib.mkOption {
        type = lib.types.nullOr lib.types.str;
        description = lib.mdDoc "The full name of the user.";
        default = null;
      };

      mail = lib.mkOption {
        type = lib.types.nullOr lib.types.mail;
        description = lib.mdDoc "The mail address of the user.";
        default = null;
      };

      defaultShell = lib.mkOption {
        type = lib.types.anything;
        description = "The default shell of the user.";
        default = null;
      };

      sudoer = lib.mkOption {
        type = lib.types.bool;
        description = lib.mdDoc "Enable `sudo` commands for this user.";
        default = false;
      };
    };
  };
in {
  options = {
    users.myUsers = lib.mkOption {
      type = lib.types.attrsOf userType;
      description = lib.mdDoc "The users for the system to create.";
      default = {};
    };
  };

  config = {
    users.users = builtins.mapAttrs
      (
        name: user: {
          description = lib.mkIf
            (user.fullName != null)
            user.fullName;
          isNormalUser = true;
          shell = lib.mkIf
            (user.defaultShell != null)
            user.defaultShell;
          extraGroups = lib.mkIf user.sudoer [
            "wheel"
          ];
        })
      config.users.myUsers;
  };
}