# flake.nix
{
  inputs = {
    nixos-hardware.url = "github:NixOS/nixos-hardware";

    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

    nixpkgs-stable.url = "github:nixos/nixpkgs/nixos-24.11";

    home-manager = {
      url = "github:nix-community/home-manager";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    disko = {
      url = "github:nix-community/disko";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    nix-flatpak = {
      url = "github:gmodena/nix-flatpak"; # unstable branch
    };

    nixarr = {
      url = "github:rasmus-kirk/nixarr";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    emacs-lsp-booster = {
      url = "github:slotThe/emacs-lsp-booster-flake";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    waybar.url = "github:Alexays/Waybar/master";

    xwayland-satellite = {
      url = "github:Supreeeme/xwayland-satellite";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    yazi = {
      url = "github:sxyazi/yazi";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    emacs-overlay = {
      url = "github:nix-community/emacs-overlay";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    nix-rice = {
      url = "github:bertof/nix-rice";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    nh = {
      url = "github:viperML/nh";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    hyprlock = {
      url = "github:hyprwm/hyprlock";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    hypridle = {
      url = "github:hyprwm/hypridle";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    musnix = {
      url = "github:musnix/musnix";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    wezterm = {
      url = "github:wez/wezterm?dir=nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    sops-nix = {
      url = "github:Mic92/sops-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    affinity-nix = {
      url = "github:mrshmllow/affinity-nix";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    isd = {
      url = "github:isd-project/isd";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    niri = {
      url = "github:sodiboo/niri-flake";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    impala = {
      url = "github:pythops/impala";
      inputs.nixpkgs.follows = "nixpkgs";
    };

    # emenel-templates.url = "git+ssh://git@gt.emenel.ca/emenel/nix-flake-templates";
    # nix-way-templates.url = "github:the-nix-way/dev-templates";

  };

  outputs =
    {
      nixpkgs,
      home-manager,
      self,
      ...
    } @inputs:

    let
      inherit (nixpkgs.lib) genAttrs replaceStrings;
      inherit (nixpkgs.lib.filesystem) packagesFromDirectoryRecursive listFilesRecursive;

      sys = "x86_64-linux";

      forAllSystems =
        function:
        genAttrs [
          "x86_64-linux"
        ] (system: function nixpkgs.legacyPackages.${system});

      nameOf = path: replaceStrings [ ".nix" ] [ "" ] (baseNameOf (toString path));

      configArgs = {
        inherit inputs;
        nix-config = self;
        pkgs-stable = inputs.nixpkgs-stable.legacyPackages.${sys};
      };

      baseHomeModules = [
        inputs.nix-flatpak.homeManagerModules.nix-flatpak
        inputs.sops-nix.homeManagerModules.sops
      ];

      baseHomeManager = {
        useGlobalPkgs = true;
        useUserPackages = true;
        backupFileExtension = "bak";
        sharedModules = baseHomeModules;
        extraSpecialArgs = configArgs;
      };

    in
    {
      packages = forAllSystems (
        pkgs:
        packagesFromDirectoryRecursive {
          inherit (pkgs) callPackage;
          directory = ./packages;
        }
      );

      nixosModules = genAttrs (map nameOf (listFilesRecursive ./modules/system)) (
        name: import ./modules/system/${name}.nix
      );

      homeModules = genAttrs (map nameOf (listFilesRecursive ./modules/home)) (
        name: import ./modules/home/${name}.nix
      );

      overlays = genAttrs (map nameOf (listFilesRecursive ./overlays)) (
        name: import ./overlays/${name}.nix
      );

      nixosConfigurations = {
        eddie = nixpkgs.lib.nixosSystem {
          system = sys;
          specialArgs = configArgs;
          modules = [
            inputs.musnix.nixosModules.musnix
            inputs.niri.nixosModules.niri
            inputs.sops-nix.nixosModules.sops
            home-manager.nixosModules.home-manager

            ./hosts/eddie/configuration.nix

            {
              home-manager = baseHomeManager // {
                users.emenel = import ./homes/emenel/default.nix;
              };
            }
          ];
        };

        media-server = nixpkgs.lib.nixosSystem {
          system = sys;
          specialArgs = configArgs;
          modules = [
            home-manager.nixosModules.home-manager
            inputs.sops-nix.nixosModules.sops
            inputs.nixarr.nixosModules.default

            ./hosts/media-server/configuration.nix

            {
              home-manager = baseHomeManager // {
                users.media = import ./homes/media/default.nix;
              };
            }
          ];
        };

        services-nixos = nixpkgs.lib.nixosSystem {
          system = sys;
          specialArgs = configArgs;
          modules = [
            inputs.sops-nix.nixosModules.sops
            home-manager.nixosModules.home-manager
            inputs.disko.nixosModules.disko

            ./hosts/emenel-services/configuration.nix

            {
              home-manager = baseHomeManager // {
                users.emenel = import ./homes/emenel-services/default.nix;
              };
            }
          ];
        };
      };
    };
}
