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

with lib;

let
  cfg = config.home.roles.emacs;

  doomEmacs = pkgs.fetchFromGitHub {
    owner = "doomemacs";
    repo = "doomemacs";
    rev = "38d94da67dc84897a4318714dcc48494c016d8c4";
    sha256 = "sha256-Uc6qONH3jjUVDgW+pPBCGC7mh88ZY05u1y37fQrsxq0=";
  };

  # Shared emacs packages
  emacsPackages = epkgs: [
    epkgs.vterm
    epkgs.treesit-grammars.with-all-grammars
  ];

  # Default emacs configuration with vterm support
  defaultEmacsPackage =
    if pkgs.stdenv.isDarwin
    then pkgs.emacs-macport.pkgs.withPackages emacsPackages
    else pkgs.emacs.pkgs.withPackages emacsPackages;

  # Path to doom config directory (relative to this file)
  doomConfigDir = ./doom;
in
{
  options.home.roles.emacs = {
    enable = mkEnableOption "Doom Emacs with vterm and tree-sitter support";

    prebuiltDoom = mkOption {
      type = types.bool;
      default = false;
      description = ''
        Use nix-doom-emacs-unstraightened to pre-build all Doom packages at
        nix build time. This eliminates the need to run `doom sync` after
        first boot, making it ideal for live USB images or immutable systems.

        When enabled, the doom configuration is read-only (stored in nix store).
      '';
    };
  };

  config = mkIf cfg.enable (mkMerge [
    # Common configuration for both modes
    {
      home.packages = [
        pkgs.emacs-all-the-icons-fonts
        pkgs.fira-code
        pkgs.fontconfig
        pkgs.graphviz
        pkgs.isort
        pkgs.nerd-fonts.fira-code
        pkgs.nerd-fonts.droid-sans-mono
        pkgs.nil # nix lsp language server
        pkgs.nixfmt-rfc-style
        (pkgs.ripgrep.override {withPCRE2 = true;})
        pkgs.pipenv
        pkgs.poetry
        pkgs.python3
      ];

      fonts.fontconfig.enable = true;
    }

    # Standard Doom Emacs mode (requires doom sync at runtime)
    (mkIf (!cfg.prebuiltDoom) {
      programs.emacs = {
        enable = true;
        package = defaultEmacsPackage;
      };

      # Mount emacs and tree-sitter grammars from nix store
      home.file = {
        "${config.xdg.configHome}/emacs".source = doomEmacs;
      };

      home.sessionPath = [
        "${config.xdg.configHome}/emacs/bin"
      ];

      home.sessionVariables = {
        DOOMDIR = "${config.xdg.configHome}/doom";
        DOOMLOCALDIR = "${config.xdg.dataHome}/doom";
      };

      # TODO: Use mkOutOfStoreSymlink instead?
      home.activation.doomConfig = lib.hm.dag.entryAfter ["writeBoundary"] ''
        # Always remove and recreate the symlink to ensure it points to the source directory
        rm -rf "${config.xdg.configHome}/doom"
        ln -sf "${config.home.homeDirectory}/nixos-configs/home/roles/emacs/doom" "${config.xdg.configHome}/doom"
      '';
    })

    # Pre-built Doom Emacs mode (no doom sync needed - ideal for live USB)
    (mkIf cfg.prebuiltDoom {
      programs.doom-emacs = {
        enable = true;
        doomDir = doomConfigDir;
        doomLocalDir = "${config.xdg.dataHome}/doom";
        # Add extra packages that aren't part of Doom but needed for our config
        extraPackages = epkgs: [
          epkgs.vterm
          epkgs.treesit-grammars.with-all-grammars
        ];
      };
    })
  ]);
}
