{
  config,
  lib,
  pkgs,
  ...
}:

let
  cfg = config.services.tailscale;

  inherit (lib)
    concatStrings
    filterAttrs
    mapAttrsToList
    mkIf
    mkOption
    optional
    types
    ;
in
{
  options.services.tailscale = {
    tailnets = mkOption {
      default = { };
      type = types.attrsOf (
        types.submodule {
          options = {
            loginServer = mkOption {
              type = types.str;
              description = "Login server for this tailnet.";
            };
            authKeyFile = mkOption {
              type = types.nullOr types.str;
              default = null;
              description = "Path to auth key secret.";
            };
            enableSSH = mkOption {
              type = types.bool;
              default = false;
            };
            acceptDNS = mkOption {
              type = types.bool;
              default = true;
            };
            default = mkOption {
              type = types.bool;
              default = false;
              description = "Connect to this tailnet on boot.";
            };
          };
        }
      );
    };
  };

  config =
    let
      defaultTailnets = filterAttrs (_: t: t.default) cfg.tailnets;
      defaultTailnet =
        if defaultTailnets == { } then null else builtins.head (builtins.attrValues defaultTailnets);

      entries = mapAttrsToList (name: tcfg: ''
        TAILNETS["${name}"]="${tcfg.loginServer}|${if tcfg.enableSSH then "true" else "false"}|${
          if tcfg.acceptDNS then "true" else "false"
        }|${if tcfg.authKeyFile != null then tcfg.authKeyFile else ""}"
      '') cfg.tailnets;

      tailnetSwitchCli = pkgs.writeShellScriptBin "tailnet-switch" ''
        set -euo pipefail

        TAILSCALE="${cfg.package}/bin/tailscale"

        declare -A TAILNETS
        ${concatStrings entries}

        CHOICE="''${1:-}"

        if [[ -z "$CHOICE" ]]; then
          if [[ -t 0 ]]; then
            CHOICE=$(printf '%s\n' "''${!TAILNETS[@]}" | sort | ${pkgs.fzf}/bin/fzf --prompt="Switch tailnet: ")
          else
            echo "Usage: tailnet-switch <tailnet-name>" >&2
            printf 'Available tailnets: %s\n' "''${!TAILNETS[@]}" >&2
            exit 1
          fi
        fi

        if [[ -z "''${TAILNETS[$CHOICE]+x}" ]]; then
          echo "Unknown tailnet: $CHOICE" >&2
          printf 'Available tailnets: %s\n' "''${!TAILNETS[@]}" >&2
          exit 1
        fi

        IFS='|' read -r LOGIN_SERVER ENABLE_SSH ACCEPT_DNS AUTH_KEY_FILE <<< "''${TAILNETS[$CHOICE]}"

        echo "Switching to: $CHOICE ($LOGIN_SERVER)"

        "$TAILSCALE" down --accept-risk=lose-ssh 2>/dev/null || true
        "$TAILSCALE" logout 2>/dev/null || true

        UP_FLAGS=("--login-server=$LOGIN_SERVER")
        [[ "$ENABLE_SSH"  == "true" ]] && UP_FLAGS+=("--ssh")
        [[ "$ACCEPT_DNS"  == "true" ]] && UP_FLAGS+=("--accept-dns")
        [[ -n "$AUTH_KEY_FILE" ]]      && UP_FLAGS+=("--auth-key=$(cat "$AUTH_KEY_FILE")")

        "$TAILSCALE" up "''${UP_FLAGS[@]}"

        echo "Switched to tailnet: $CHOICE"
      '';
    in
    mkIf cfg.enable {
      assertions = [
        {
          assertion =
            (builtins.length (builtins.attrValues (filterAttrs (_: t: t.default) cfg.tailnets))) <= 1;
          message = "services.tailscale.tailnets: Only one tailnet can be set as default.";
        }
        {
          assertion = cfg.tailnets != { };
          message = "services.tailscale.tailnets: At least one tailnet must be defined.";
        }
      ];

      services.tailscale = mkIf (defaultTailnet != null) (
        with defaultTailnet;
        {
          inherit authKeyFile;
          extraSetFlags = optional enableSSH "--ssh" ++ optional acceptDNS "--accept-dns";
          extraUpFlags = [
            "--login-server=${loginServer}"
          ]
          ++ optional enableSSH "--ssh"
          ++ optional acceptDNS "--accept-dns";
        }
      );

      environment.systemPackages = [ tailnetSwitchCli ];

      environment.shellAliases.ts = "${cfg.package}/bin/tailscale";

      networking.firewall.trustedInterfaces = [ cfg.interfaceName ];
    };
}
