{ lib,... }:
let
  inherit (lib) mkOption;
  inherit (lib.types) attrsOf coercedTo listOf str submodule nullOr port bool oneOf anything enum;
  pathEntryType = coercedTo str (path: { inherit path; }) (submodule {
    options = {
      path = mkOption { type = str; };
      owner = mkOption {
        type = str;
        default = "root:root";
      };
      mode = mkOption {
        type = str;
        default = "0755";
      };
      dirs = mkOption {
        type = listOf str;
        default = [ ];
      };
    };
  });
  mkPathOption = defaultPath: defaults: mkOption {
    type = pathEntryType;
    default = { path = defaultPath; } // defaults;
  };
in with lib; {
    domain = mkOption { type = types.str; };
    mail = {
      domain = mkOption { type = types.nullOr types.str; default = null;};
      server = mkOption { type = types.nullOr types.str; default = null;};

    };

    path = mkOption {
      type = types.submodule {
        freeformType = attrsOf pathEntryType;
        options = {
          config = mkPathOption "/media/config" { };
          data = mkPathOption "/media/data" { };
          download = mkPathOption "/media/data/download" { owner = "1000:1000"; };
          cloud = mkPathOption "/media/media/cloud" { owner = "33:33"; };
          film = mkPathOption "/media/media/film" { owner = "1000:1000"; };
          book = mkPathOption "/media/media/book" { owner = "1000:1000"; };
          manga = mkPathOption "/media/media/manga" { owner = "1000:1000"; };
          photo = mkPathOption "/media/media/photo" { owner = "1000:1000"; };
          # music = mkPathOption "/media/media/music" { owner = "1000:1000"; };

          dlComplete = mkPathOption "/media/download/complete" { owner = "1000:1000"; };
          dlIncomplete = mkPathOption "/media/download/incomplete" { owner = "1000:1000"; };
          dlConverted = mkPathOption "/media/download/converted" { owner = "1000:1000"; };
        };
      };
      default = {};
    };

    colorScheme = mkOption {
      type = types.attrs;
      default = (lib.evalModules { modules =[ { freeformType = with lib.types; attrsOf anything; } ../colors ];}).config.colorScheme ;
    };
    loadedContainers = lib.mkOption {
      readOnly = true;
       type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
        options = {
          name = lib.mkOption {type = lib.types.str; default = name;};
          requires = {
            secrets = lib.mkOption {
              type = lib.types.listOf lib.types.str;
              default = [ ];
            };
            databases = lib.mkOption {
              type = lib.types.listOf lib.types.str;
              default = [ ];
            };
          };

          exports = {
            authentik = {
              blueprints = lib.mkOption {
                type = lib.types.listOf lib.types.str;
                default = [ ];
              };
            };
          };

          runtime = {
            paths = lib.mkOption {type = lib.types.listOf lib.types.attrs; default = [ ];};
            containers = lib.mkOption {type = lib.types.attrsOf lib.types.attrs; default = { };};
            vm = lib.mkOption {type = lib.types.nullOr lib.types.attrs; default = null;};
            cron = lib.mkOption {type = lib.types.listOf lib.types.str; default = [ ];};
            setup = lib.mkOption {
              type = lib.types.submodule {
                options = {
                  trigger = lib.mkOption {type = lib.types.str; default = "";};
                  script = lib.mkOption {type = lib.types.nullOr lib.types.package; default = null;};
                  envFile = lib.mkOption {
                    type = with lib.types; coercedTo str (x: [x]) (listOf str);
                    default = [ ];
                  };
                };
              };
              default = { };
            };
          };
        };
       }));
        
    };
    containers  = mkOption {
      type = types.attrsOf (types.submodule {
        options = {
          subdomain = mkOption { type = types.nullOr types.str; default=null;};
          subpath = mkOption { type = types.nullOr types.str; default=null;};
          port = mkOption { type = types.nullOr types.port; default = null; };
          extra = mkOption { type = types.attrs; default = {}; };
        };
      });
      default = {};
    };
    openssh = mkOption {
      type = types.bool;
      default = false;
    };
    wireguard = mkOption {
      type = types.bool;
      default = false;
    };
    web = mkOption {
      type = types.bool;
      default = false;
    };
    ipfw = {
      enable = mkOption {
        type = types.bool;
        default = false;
      };
      ifs = mkOption {
        type = types.listOf types.str;
        default = [ ];
      };
      ports = mkOption {
        type = types.listOf (types.listOf (types.oneOf [ types.str types.int ]));
        default = [];
        description = "Forwarding rules: [ [srcInterface dstAddr srcPort dstPort] ... ]";
        example = [
          [ "ens3" "10.10.1.2" "IPV6" 22 2222 ]
          [ "ens3" "10.10.1.2" "IPV6" 80 80 ]
          [ "ens3" "10.10.1.2" "IPV6" 443 443 ]
        ];
      };
    };

    db = mkOption {
      type = types.listOf (types.str);
      default = [ ];
    };

}
