{
  config,
  lib,
  pkgs,
  ...
}: let
  cfg = config.marleyos.programs.git;

  inherit (config.marleycfg) my;
in {
  options.marleyos.programs.git.enable = lib.mkEnableOption "git";

  imports = [
    ./aliases.nix
  ];

  config = lib.mkIf cfg.enable {
    home.packages = with pkgs; [
      gum
    ];

    #     ██████╗ ██╗████████╗
    #    ██╔════╝ ██║╚══██╔══╝
    #    ██║  ███╗██║   ██║
    #    ██║   ██║██║   ██║
    #    ╚██████╔╝██║   ██║
    #     ╚═════╝ ╚═╝   ╚═╝

    programs.git = {
      enable = true;

      userName = my.git.name;
      userEmail = my.git.email;

      signing = {
        signByDefault = true;
        key = null;
      };

      lfs.enable = true;

      ignores = [
        "tags*"
        "gems.tags"
      ];

      attributes = [
        # Auto-normalize line endings.
        "* text=auto"

        "*.png binary"
        "*.jpg binary"
        "*.jpeg binary"
        "*.bmp binary"
      ];

      #    ██████╗ ██╗███████╗███████╗████████╗ █████╗ ███████╗████████╗██╗ ██████╗
      #    ██╔══██╗██║██╔════╝██╔════╝╚══██╔══╝██╔══██╗██╔════╝╚══██╔══╝██║██╔════╝
      #    ██║  ██║██║█████╗  █████╗     ██║   ███████║███████╗   ██║   ██║██║
      #    ██║  ██║██║██╔══╝  ██╔══╝     ██║   ██╔══██║╚════██║   ██║   ██║██║
      #    ██████╔╝██║██║     ██║        ██║   ██║  ██║███████║   ██║   ██║╚██████╗
      #    ╚═════╝ ╚═╝╚═╝     ╚═╝        ╚═╝   ╚═╝  ╚═╝╚══════╝   ╚═╝   ╚═╝ ╚═════╝

      difftastic = {
        enable = true;
      };

      #     ██████╗ ██████╗ ███╗   ██╗███████╗██╗ ██████╗
      #    ██╔════╝██╔═══██╗████╗  ██║██╔════╝██║██╔════╝
      #    ██║     ██║   ██║██╔██╗ ██║█████╗  ██║██║  ███╗
      #    ██║     ██║   ██║██║╚██╗██║██╔══╝  ██║██║   ██║
      #    ╚██████╗╚██████╔╝██║ ╚████║██║     ██║╚██████╔╝
      #     ╚═════╝ ╚═════╝ ╚═╝  ╚═══╝╚═╝     ╚═╝ ╚═════╝

      extraConfig = {
        core = {
          # Whitespace types to treat as errors.
          # blank-at-eol: looks for spaces at EOL.
          # -blank-at-eof: allows blank lines at EOF.
          # space-before-tab: looks for spaces immediately before tabs at the
          #   beginning of the line.
          whitespace = "blank-at-eol,-blank-at-eof,space-before-tab";

          # Prevent showing files whose names contain non-ASCII symbols as
          # unversioned.
          precomposeunicode = false;

          # Speed up commands involving untracked files such as `git status`.
          untrackedCache = true;
        };

        # Laravel Sail makes permissions fucky so this is required...
        safe.directory = "/home/${my.name}/hackin/*";

        # Do not guess the user's identity.
        user.useConfigOnly = true;

        color.diff = "always";

        pretty = {
          lo = "tformat:%C(auto)%h%C(reset)%C(auto)%d%C(reset) %s %C(italic blue)%ad%C(reset) %C(241)%aN%C(reset)";
          lc = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n";
          lt = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n%w(0,7,7)%+(trailers:only,unfold)";
          lf = "format:%C(auto)%h%C(reset)%C(auto)%d%C(reset)   %C(italic 239)[P: %p] [T: %t]%C(reset)%n%C(white)Author:%C(reset)   %aN %C(241)<%aE>%C(reset)%n          %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%n%C(white)Commit:%C(reset)   %cN %C(241)<%cE>%C(reset)   %C(italic 239)[GPG: %G?% GK]%C(reset)%n          %C(italic blue)%cd%C(reset) %C(italic cyan)(%cr)%C(reset)%w(0,4,4)%n%n%C(bold)%s%C(reset)%n%n%-b%n%n%-N%n";
          rlo = "tformat:%C(auto)%h%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset)%C(auto)%d%C(reset) %gs %C(italic blue)%ad%C(reset) %C(241)%aN%C(reset)";
          rlc = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n %C(white)⤷%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset) %gs %C(241)- %gN <%gE>%C(reset)%n";
          rlt = "format:%C(auto)%h%C(reset) %C(white)-%C(reset) %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%C(auto)%d%C(reset)%n %C(white)⤷%C(reset) %s %C(241)- %aN <%aE>%C(reset)%n %C(white)⤷%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset) %gs %C(241)- %gN <%gE>%C(reset)%n%w(0,7,7)%+(trailers:only,unfold)";
          rlf = "format:%C(auto)%h%C(reset) %C(bold yellow)(%C(magenta)%gd%C(bold yellow))%C(reset)%C(auto)%d%C(reset)   %C(italic 239)[P: %p] [T: %t]%C(reset)%n%C(white)Author:%C(reset)   %aN %C(241)<%aE>%C(reset)%n          %C(italic blue)%ad%C(reset) %C(italic cyan)(%ar)%C(reset)%n%C(white)Commit:%C(reset)   %cN %C(241)<%cE>%C(reset)   %C(italic 239)[GPG: %G?% GK]%C(reset)%n          %C(italic blue)%cd%C(reset) %C(italic cyan)(%cr)%C(reset)%n%C(white)Reflog:%C(reset)   %gN %C(241)<%gE>%C(reset)%n          %C(italic)%gs%C(reset)%w(0,4,4)%n%n%C(bold)%s%C(reset)%n%n%-b%n%n%-N%n";
        };

        init.defaultBranch = "main";

        status.showstash = true;

        push = {
          autoSetupRemote = true;

          # Push tags automatically.
          followTags = true;
        };

        rebase.autosquash = true;

        merge = {
          # Use nvim for merging, specifically the view showing LOCAL, MERGED,
          # REMOTE.
          tool = "nvimdiff2";

          # Include summaries of merged commits in merge commit messages.
          log = true;

          # delta.
          conflictstyle = "diff3";
        };

        mergetool = {
          keepBackup = false;
          hideResolved = true;
        };

        diff = {
          # Detect when files are copied as well as renamed.
          renames = "copies";

          # delta
          colorMoved = "default";
        };

        # Fix whitespace errors when applying a patch, as specified in
        # core.whitespace.
        apply.whitespace = "fix";

        branch = {
          # Show most recently changed branches first.
          sort = "-committerdate";

          autoSetupMerge = "simple";
        };

        credential.helper = "store";
      };
    };

    #    ███╗   ███╗██╗███████╗ ██████╗
    #    ████╗ ████║██║██╔════╝██╔════╝
    #    ██╔████╔██║██║███████╗██║
    #    ██║╚██╔╝██║██║╚════██║██║
    #    ██║ ╚═╝ ██║██║███████║╚██████╗
    #    ╚═╝     ╚═╝╚═╝╚══════╝ ╚═════╝

    home.shellAbbrs = {
      g = "git";
    };

    programs.fish.functions = {
      git_develop_branch =
        # fish
        ''
          command git rev-parse --git-dir &>/dev/null || return
          set -l branch

          for branch in dev devel develop development
            if command git show-ref -q --verify refs/heads/$branch
              echo $branch
              return 0
            end
          end

          echo develop
          return 1
        '';

      git_main_branch =
        # fish
        ''
          command git rev-parse --git-dir &>/dev/null || return
          set -l ref

          for ref in
              refs/{heads,remotes/{origin,upstream}}/{main,trunk,mainline,default,master}
              if command git show-ref -q --verify $ref
                  echo (basename $ref)
                  return 0
              end
          end

          echo main
          return 1
        '';

      git_current_branch =
        # fish
        ''
          set -l ref (git symbolic-ref --quiet HEAD 2>/dev/null)
          set -l ret $status

          if [ $ret -ne 0 ]
              [ $ret -eq 128 ] && return # no git repo
              set ref (git rev-parse --short HEAD 2>/dev/null) || return
          end

          echo (string replace "refs/heads/" "" $ref)
        '';

      git_open =
        # fish
        ''
          set -f origin "$(git remote get-url origin)"

          switch "$origin"
              case "*github*"
                  if command -v gh &>/dev/null
                      gh repo view --web &>/dev/null
                  else
                      set_color red
                      echo "[ERROR] Install gh-cli to open Github repos." >&2
                      set_color normal
                      return 1
                  end
              case "https://*"
                  open '$origin' >/dev/null &
              case "*"
                  set_color red
                  printf "[ERROR] Unrecognized origin %s" "$origin" >&2
                  return 1
          end
        '';
    };
  };
}
#    ███╗   ██╗ ██████╗ ████████╗███████╗███████╗
#    ████╗  ██║██╔═══██╗╚══██╔══╝██╔════╝██╔════╝
#    ██╔██╗ ██║██║   ██║   ██║   █████╗  ███████╗
#    ██║╚██╗██║██║   ██║   ██║   ██╔══╝  ╚════██║
#    ██║ ╚████║╚██████╔╝   ██║   ███████╗███████║
#    ╚═╝  ╚═══╝ ╚═════╝    ╚═╝   ╚══════╝╚══════╝
# PATH VALUES:
# :/ - all files within the root of the working tree, so all files in the
#   repo, a la git add's --all option.
# A note on reset, restore, and revert, paraphrased from `man git`, plus my
# own on `rm`:
#
# revert - make a new commit that reverts a previous commit.
# restore - undo uncommitted changes in the working tree.
# reset - update the branch and change commit history.
# rm - same as system rm; remove files, either from git's knowledge, the
#   working directory, or both.
#
# These are not a description of the *possible* uses, rather a narrowing of
# the *intended* uses.

