# home/lib/default.nix
# Profile loading utilities for home-manager configurations.
#
# Usage:
#   let homeLib = import ../lib { inherit lib; };
#   in {
#     imports = [
#       (homeLib.mkHomeConfig { profiles = ["coding" "gaming"]; context = "desktop"; })
#     ];
#   }
{lib}: let
  # Infrastructure layer — nixpkgs overlays, nix-colors, m3ta-nixpkgs modules.
  # Always loaded on every host.
  commonModule = ../common;

  # Base user environment — shell (nushell, starship), CLI tools, secrets.
  # Always loaded on every host.
  baseModule = ../base;

  # Context-specific modules — desktop and server are mutually exclusive.
  contextModuleMap = {
    desktop = ../desktop;
    server = ../server;
  };

  # Profile modules — freely combinable additions on top of base + context.
  profileModuleMap = {
    coding = ../coding;
    gaming = ../profiles/gaming;
    media = ../profiles/media;
  };
in {
  # Generate a home-manager module with imports based on profiles and context.
  #
  # Args:
  #   profiles: list of profile names (e.g. ["coding" "gaming" "media"])
  #   context: host context, one of "desktop" | "server" | null
  #
  # Returns: a home-manager module attrset with imports and assertions.
  #   Desktop and server contexts are mutually exclusive by design — passing
  #   any value other than "desktop", "server", or null causes an assertion
  #   failure at evaluation time.
  mkHomeConfig = {
    profiles ? [],
    context ? null,
  }: let
    contextImport =
      if context == "desktop"
      then [contextModuleMap.desktop]
      else if context == "server"
      then [contextModuleMap.server]
      else [];

    # Partition profiles into known and unknown for assertion + safe import.
    unknownProfiles =
      builtins.filter
      (profileName: ! builtins.hasAttr profileName profileModuleMap)
      profiles;

    # Only import known profiles; the assertion below catches unknowns.
    activeProfiles =
      builtins.filter
      (profileName: builtins.hasAttr profileName profileModuleMap)
      profiles;

    profileImports = map (profileName: profileModuleMap.${profileName}) activeProfiles;

    contextStr =
      if context == null
      then "null"
      else context;
  in {
    imports =
      [commonModule baseModule]
      ++ contextImport
      ++ profileImports;

    assertions = [
      {
        assertion = builtins.elem context ["desktop" "server" null];
        message =
          "m3ta home: context must be 'desktop', 'server', or null"
          + " (got: '${contextStr}')";
      }
      {
        assertion = unknownProfiles == [];
        message =
          "m3ta home: unknown profiles requested:"
          + " [ ${builtins.concatStringsSep " " unknownProfiles} ]."
          + " Valid profiles are:"
          + " [ ${builtins.concatStringsSep " " (builtins.attrNames profileModuleMap)} ]";
      }
    ];
  };
}
