{ zentralwerk, config, lib, ... }:

let
  inherit (config.networking) hostName;

  zwNets = zentralwerk.lib.config.site.net;
  zwHostConfig = zentralwerk.lib.config.site.hosts.${hostName};
  zwHostBridges = builtins.attrNames (
    lib.filterAttrs (_: { type, ... }: type == "bridge")
      zwHostConfig.interfaces
  );

in
{
  options = with lib; {
    c3d2.server.bridgePorts = mkOption {
      description = "Additional interfaces to attach to bridges";
      type = with types; attrsOf (listOf str);
      default = {};
    };
  };

  config = {
    networking = {
      useDHCP = false;
      useNetworkd = true;
    };

    boot.kernelParams = [
      # Prevents automatic creation of interface bond0 by the kernel
      "bonding.max_bonds=0"
    ];

    systemd.network = {
      enable = true;

      netdevs = {
        bond0.netdevConfig = {
          Kind = "bond";
          Name = "bond0";
        };
        # LACP
        bond0.bondConfig.Mode = "802.3ad";
      } // (
        builtins.foldl' (result: net: result // {
          # Bridges are named just like the corresponding net.
          "${net}" = {
            netdevConfig = {
              Kind = "bridge";
              Name = "${net}";
            };
            extraConfig = ''
            [Bridge]
            ForwardDelaySec=2
            STP=true
          '';
          };
          # External VLAN interface
          "ext-${net}" = {
            netdevConfig = {
              Kind = "vlan";
              Name = "ext-${net}";
            };
            vlanConfig.Id = zwNets.${net}.vlan;
          };
        }) {} zwHostBridges
      );

      networks = {
        en = {
          # physical ethernet ports
          matchConfig.Name = "en*";
          networkConfig = {
            Bond = "bond0";
            LLDP = true;
            EmitLLDP = true;
          };
        };
        bond0 = {
          DHCP = "no";
          matchConfig.Name = "bond0";
          networkConfig = {
            VLAN = map (net: "ext-${net}") zwHostBridges;
            LinkLocalAddressing = "no";
            LLDP = true;
            EmitLLDP = true;
          };
        };
      } // (builtins.foldl' (result: net: result // {
        "${net}" = {
          matchConfig.Name = net;
          networkConfig = {
            LLDP = true;
            EmitLLDP = true;
            DHCP = "no";
            IPv6AcceptRA = "no";
          } // (lib.optionalAttrs (! zwNets.${net}.hosts4 ? ${hostName})) {
            # Disable all automatic addressing on bridges. It will delay
            # networkd going into operational state.
            LinkLocalAddressing = lib.mkDefault "no";
          };
          addresses =
            let
              netConfig = zwNets.${net};
              address = netConfig.hosts4.${hostName};
              prefixLen = netConfig.subnet4Len;
            in
              lib.optional (netConfig.hosts4 ? ${hostName}) {
                addressConfig.Address = "${address}/${toString prefixLen}";
              } ++
              builtins.concatMap (hosts6:
                lib.optional (hosts6 ? ${hostName}) {
                  addressConfig.Address = "${hosts6.${hostName}}/64";
                }
              ) (builtins.attrValues netConfig.hosts6);

          gateway = lib.optionals (net == "cluster") [
            zwNets.cluster.hosts4.cls-gw
            zwNets.cluster.hosts6.dn42.cls-gw
          ];
        };
        "ext-${net}" = {
          matchConfig.Name = "ext-${net}";
          # Attach eth*/bond0/VLAN to bridge
          networkConfig.Bridge = net;
        };
        "ports-${net}" = {
          matchConfig.Name = "${net}-*";
          networkConfig.Bridge = net;
        };
      }) {} zwHostBridges);
    };
  };
}
