{
  config,
  options,
  lib,
  pkgs,
  ...
}:
let
  inherit (lib)
    attrValues
    filter
    filterAttrs
    getExe
    hasSuffix
    head
    id
    length
    listToAttrs
    mkDefault
    mkEnableOption
    mkIf
    mkOption
    mkPackageOption
    replaceStrings
    ;

  inherit (lib.types)
    listOf
    nullOr
    str
    submodule
    ;

  cfg = config.programs.radicle;
  opt = options.programs.radicle;

  configFile = rec {
    format = pkgs.formats.json { };
    name = "config.json";
    path = pkgs.runCommand name { nativeBuildInputs = [ cfg.cli.package ]; } ''
      mkdir keys
      echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID/this/is/not/a/real/key/only/a/placeholder" \
        > keys/radicle.pub
      cp ${format.generate name cfg.settings} ${name}
      RAD_HOME=$PWD rad config
      cp ${name} $out
    '';
  };

  publicExplorerSuffix = "$rid$path";
in
{
  meta.maintainers = with lib.maintainers; [
    lorenzleutgeb
    matthiasbeyer
  ];

  options = {
    programs.radicle = {
      enable = mkEnableOption "Radicle";

      cli.package = mkPackageOption pkgs "radicle-node" { };

      uri = {
        rad = {
          browser = {
            enable = mkOption {
              description = "Whether to enable `rad:`-URI handling by web browser";
              default =
                (hasSuffix publicExplorerSuffix cfg.settings.publicExplorer) && pkgs.stdenv.hostPlatform.isLinux;
              defaultText = "`true` if a suitable public explorer is detected.";
              example = false;
            };
            preferredNode = mkOption {
              type = str;
              description = "The hostname of an instance of `radicle-node`, reachable via HTTPS.";
              default = "iris.radicle.xyz";
              example = "radicle-node.example.com";
            };
          };
          vscode = {
            enable = mkEnableOption "`rad:`-URI handling by VSCode";
            extension = mkOption {
              type = str;
              description = "The unique identifier of the VSCode extension that should handle `rad:`-URIs.";
              default = "radicle-ide-plugins-team.radicle";
            };
          };
        };
        web-rad =
          let
            detected =
              let
                detectionList = attrValues (
                  filterAttrs (n: _: config.programs.${n}.enable) {
                    librewolf = "librewolf.desktop";
                    firefox = "firefox.desktop";
                    chromium = "chromium-browser.desktop";
                  }
                );
              in
              lib.optionals (detectionList == [ ]) (head detectionList);
          in
          {
            enable = mkEnableOption "`web+rad:`-URI handling by web browser";
            browser = mkOption {
              description = ''
                Name of the XDG Desktop Entry for your browser.
                LibreWolf, Firefox and Chromium configured via home-manager will
                be detected automatically. The value of this option should likely
                be the same as the output of
                `xdg-mime query default x-scheme-handler/https`.
              '';
              type = nullOr str;
              default = detected;
              defaultText = "Automatically detected browser.";
              example = "brave.desktop";
            };
          };
      };

      settings = mkOption {
        default = { };
        description = "Radicle configuration, written to `~/.radicle/config.json.";

        type = submodule {
          freeformType = configFile.format.type;
          options = {
            publicExplorer = mkOption {
              type = str;
              description = "HTTPS URL pattern used to generate links to view content on Radicle via the browser.";
              default = "https://app.radicle.xyz/nodes/$host/$rid$path";
              example = "https://radicle.example.com/nodes/seed.example.com/$rid$path";
            };

            node = {
              alias = mkOption {
                type = str;
                description = "Human readable alias for your node.";
                default = config.home.username;
                defaultText = lib.literalExpression "config.home.username";
              };
              listen = mkOption {
                type = listOf str;
                description = "Addresses to bind to and listen for inbound connections.";
                default = [ ];
                example = [ "127.0.0.1:58776" ];
              };
            };
          };
        };
      };
    };
  };

  config = mkIf cfg.enable {
    assertions = [
      {
        assertion =
          !pkgs.stdenv.hostPlatform.isLinux
          -> (
            (filter id [
              cfg.uri.rad.browser.enable
              cfg.uri.rad.vscode.enable
            ]) == [ ]
          );
        message = "`rad:`-URI handlers are only supported on Linux.";
      }
      {
        assertion = cfg.uri.web-rad.enable -> cfg.uri.web-rad.browser != null;
        message = "Could not detect preferred browser. Please set `${toString opt.uri.web-rad.browser}`.";
      }
      {
        assertion =
          1 >= length (
            filter id [
              cfg.uri.rad.browser.enable
              cfg.uri.rad.vscode.enable
            ]
          );
        message = "At most one `rad:`-URI handler may be enabled.";
      }
      {
        assertion =
          cfg.uri.rad.browser.enable -> hasSuffix publicExplorerSuffix cfg.settings.publicExplorer;
        message = "${opt.uri.rad.browser.enable} is only compatible with a public explorer URL ending in '${publicExplorerSuffix}' but '${cfg.settings.publicExplorer}' does not end with '${publicExplorerSuffix}'.";
      }
    ];

    home = {
      packages = [ cfg.cli.package ];
      file.".radicle/${configFile.name}".source = configFile.path;
    };

    xdg = {
      mimeApps.defaultApplications = {
        "x-scheme-handler/rad" =
          let
            isEnabled = cfg.uri.rad.browser.enable || cfg.uri.rad.vscode.enable;

            handlerTarget =
              if cfg.uri.rad.browser.enable then
                "rad-to-browser.desktop"
              else if cfg.uri.rad.vscode.enable then
                "rad-to-vscode.desktop"
              else
                throw "unreachable";

            handler = mkDefault handlerTarget;
          in
          mkIf isEnabled handler;

        "x-scheme-handler/web+rad" = mkIf cfg.uri.web-rad.enable (mkDefault cfg.uri.web-rad.browser);
      };
      desktopEntries =
        let
          mkHandler =
            {
              name,
              shortName,
              prefix,
            }:
            {
              name = "Open Radicle URIs with ${name}";
              genericName = "Code Forge";
              categories = [
                "Development"
                "RevisionControl"
              ];
              exec = getExe (
                pkgs.writeShellApplication {
                  name = "rad-to-${shortName}";
                  meta.mainProgram = "rad-to-${shortName}";
                  text = ''xdg-open "${prefix}$1"'';
                }
              );
              mimeType = [ "x-scheme-handler/rad" ];
              noDisplay = true;
            };

          toHandler = v: {
            name = "rad-to-${v.shortName}";
            value = mkIf cfg.uri.rad.${v.shortName}.enable (mkHandler v);
          };
        in
        listToAttrs (
          map toHandler [
            {
              name = "Web Browser";
              shortName = "browser";
              prefix =
                replaceStrings
                  [ "$host" publicExplorerSuffix ]
                  [
                    cfg.uri.rad.browser.preferredNode
                    ""
                  ]
                  cfg.settings.publicExplorer;
            }
            {
              name = "VSCode";
              shortName = "vscode";
              prefix = "vscode://${cfg.uri.rad.vscode.extension}/";
            }
          ]
        );
    };
  };
}
