# PAIML Sovereign Stack - Nix Flake Template
# Generated by entrenar sovereign deployment tooling
#
# Usage:
#   nix build        # Build default package
#   nix develop      # Enter dev shell
#   nix flake check  # Run all checks
#
# For air-gapped deployment:
#   1. Build on a machine with network: nix build --out-link result
#   2. Copy closure: nix copy --to file://./store result
#   3. Transfer ./store to air-gapped machine
#   4. Import on air-gapped machine: nix copy --from file://./store result

{
  description = "{{DESCRIPTION}}";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    rust-overlay = {
      url = "github:oxalica/rust-overlay";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    crane = {
      url = "github:ipetkov/crane";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    flake-utils.url = "github:numtide/flake-utils";
  };

  outputs = { self, nixpkgs, rust-overlay, crane, flake-utils, ... }:
    flake-utils.lib.eachSystem [ {{SYSTEMS}} ] (system:
      let
        overlays = [ (import rust-overlay) ];
        pkgs = import nixpkgs {
          inherit system overlays;
        };

        # Rust toolchain
        rustToolchain = pkgs.rust-bin.stable."{{RUST_VERSION}}".default.override {
          extensions = [ "rust-src" "rust-analyzer" ];
          targets = [ "wasm32-unknown-unknown" ];  # For WASM support
        };

        craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchain;

        # Source filtering
        src = craneLib.cleanCargoSource ./.;

        # Build dependencies
        buildInputs = with pkgs; [
          openssl
          pkg-config
          {{#GPU_SUPPORT}}
          # GPU Support
          cudatoolkit
          cudnn
          {{/GPU_SUPPORT}}
        ] ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [
          pkgs.darwin.apple_sdk.frameworks.Security
          pkgs.darwin.apple_sdk.frameworks.CoreFoundation
        ];

        nativeBuildInputs = with pkgs; [
          pkg-config
        ];

        # Common arguments for crane
        commonArgs = {
          inherit src buildInputs nativeBuildInputs;
        };

        # Build dependencies first (for caching)
        cargoArtifacts = craneLib.buildDepsOnly commonArgs;

        # Individual crate builds
        {{#CRATES}}
        {{NAME}} = craneLib.buildPackage (commonArgs // {
          inherit cargoArtifacts;
          pname = "{{NAME}}";
          {{#FEATURES}}
          cargoExtraArgs = "--features {{FEATURES}}";
          {{/FEATURES}}
        });
        {{/CRATES}}

      in {
        # Packages
        packages = {
          {{#CRATES}}
          {{NAME}} = {{NAME}};
          {{/CRATES}}
          default = {{DEFAULT_PACKAGE}};

          # Bundle for air-gapped deployment
          sovereign-bundle = pkgs.runCommand "sovereign-bundle" {} ''
            mkdir -p $out
            {{#CRATES}}
            cp -r ${{{NAME}}} $out/{{NAME}}
            {{/CRATES}}
          '';
        };

        # Development shell
        devShells.default = pkgs.mkShell {
          inputsFrom = [ {{DEFAULT_PACKAGE}} ];
          buildInputs = with pkgs; [
            rustToolchain
            rust-analyzer
            cargo-watch
            cargo-edit
            cargo-expand
            cargo-nextest
            cargo-llvm-cov

            # Documentation
            mdbook

            # Formatting
            nixpkgs-fmt
            treefmt
          ];

          shellHook = ''
            echo "PAIML Sovereign Stack Development Environment"
            echo "Rust: $(rustc --version)"
            echo ""
            echo "Commands:"
            echo "  cargo build    - Build all crates"
            echo "  cargo test     - Run all tests"
            echo "  nix build      - Build with Nix"
            echo ""
          '';
        };

        # CI checks
        checks = {
          # Clippy lints
          clippy = craneLib.cargoClippy (commonArgs // {
            inherit cargoArtifacts;
            cargoClippyExtraArgs = "--all-targets -- -D warnings";
          });

          # Tests
          test = craneLib.cargoNextest (commonArgs // {
            inherit cargoArtifacts;
            partitions = 1;
            partitionType = "count";
          });

          # Formatting
          fmt = craneLib.cargoFmt {
            inherit src;
          };

          # Documentation
          doc = craneLib.cargoDoc (commonArgs // {
            inherit cargoArtifacts;
            RUSTDOCFLAGS = "-D warnings";
          });
        };

        # For Cachix binary cache
        apps.push-to-cachix = {
          type = "app";
          program = toString (pkgs.writeShellScript "push-to-cachix" ''
            ${pkgs.cachix}/bin/cachix push paiml ${self.packages.${system}.default}
          '');
        };
      });

  # NixOS module for system-wide installation
  nixosModules.default = { config, lib, pkgs, ... }: {
    options.services.paiml = {
      enable = lib.mkEnableOption "PAIML Sovereign Stack";
      package = lib.mkOption {
        type = lib.types.package;
        default = self.packages.${pkgs.system}.default;
        description = "The PAIML package to use";
      };
    };

    config = lib.mkIf config.services.paiml.enable {
      environment.systemPackages = [ config.services.paiml.package ];
    };
  };
}
