{ config, pkgs, lib, extra, ... }:
{
  nixpkgs.config.allowUnfree = true;

  home.username = "${extra.user}";
  home.homeDirectory = "/home/${extra.user}";

  # This value determines the Home Manager release that your configuration is
  # compatible with. This helps avoid breakage when a new Home Manager release
  # introduces backwards incompatible changes.
  #
  # You should not change this value, even if you update Home Manager. If you do
  # want to update the value, then make sure to first check the Home Manager
  # release notes.
  home.stateVersion = "23.05"; # Please read the comment before changing.

  # Home Manager is pretty good at managing dotfiles. The primary way to manage
  # plain files is through 'home.file'.
  xdg.configFile = {
    "nvim".source = ./nvim;
    "foot".source = ./foot;
    "hypr".source = ./hypr;
  };

  xdg.dataFile = {
    "nvim/lazy-lock.json".source = config.lib.file.mkOutOfStoreSymlink "/home/nikos/.dotfiles/lazy-lock.json";
  };

  # The home.packages option allows you to install Nix packages into your
  # environment.
  home.packages = with pkgs; [
    just
    ripgrep # "rg" cli, alternative to grep, used by nvim
    fd # find alternative, used by nvim
    lsd # "ls" alternative
    zoxide # "z" command
    nerd-fonts.jetbrains-mono
    devenv
    devbox
  ];

  fonts.fontconfig.enable = true;

  programs.git = {
    enable = true;
    userName = "Nikos Papadakis";
    userEmail = "nikos@papadakis.xyz";
    signing.key = "78871F9905ADFF02";
    signing.signByDefault = true;
    includes = [
      {
        contents = {
          init.defaultBranch = "main";
          pull.rebase = true;
        };
      }
    ];
  };

  programs.fish = {
    enable = true;
    shellInit = lib.strings.concatStringsSep "\n" ([
      (builtins.readFile ./fish/config.fish)
    ] ++ lib.attrsets.mapAttrsToList
      (
        name: value: builtins.readFile (./fish/functions + ("/" + name))
      )
      (builtins.readDir ./fish/functions)
    );
  };

  programs.neovim = {
    enable = true;
    defaultEditor = true;
    package = pkgs.neovim;
    extraPackages = [
      pkgs.nil # Nix lsp
      pkgs.nixpkgs-fmt # Nix formatter
      pkgs.efm-langserver # Generic language server
      pkgs.lua-language-server # Lua lsp
      pkgs.gopls # Go lsp
      pkgs.lexical # Elixir lsp
      pkgs.shellcheck
      pkgs.nodePackages.intelephense # PHP lsp
      pkgs.nodePackages.typescript-language-server
      pkgs.nodePackages.bash-language-server
      pkgs.prettierd
      pkgs.eslint_d
      pkgs.zls
      pkgs.nodejs_23
    ];
  };

  programs.direnv = {
    enable = true;
    nix-direnv.enable = true;
  };

  # Let Home Manager install and manage itself.
  programs.home-manager.enable = true;
}