{
  description = "PhotonCloud local CI gates (Nix-first, CI-provider-agnostic)";

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

    flake-utils.url = "github:numtide/flake-utils";
    photoncloud.url = "path:../..";

    rust-overlay = {
      url = "github:oxalica/rust-overlay";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

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

        # Use a complete toolchain to ensure host `std` is present under Nix
        # (fixes: "can't find crate for `std`").
        rustToolchain = pkgs.rust-bin.stable.latest.complete;

        # rust-overlay components (provide cargo-fmt / clippy-driver reliably in PATH)
        rustfmtComponent = pkgs.rust-bin.stable.latest.rustfmt;
        clippyComponent = pkgs.rust-bin.stable.latest.clippy;

        ciInventory = builtins.fromJSON (builtins.readFile ./workspaces.json);
        wsList = map (workspace: workspace.name) ciInventory.workspaces;
        supportedWorkspaces = pkgs.lib.concatStringsSep ", " wsList;

        gate = pkgs.writeShellApplication {
          name = "photoncloud-gate";

          runtimeInputs = with pkgs; [
            bash
            coreutils
            findutils
            gnugrep
            gawk
            git
            jq
            rustToolchain
            rustfmtComponent
            clippyComponent
            protobuf
            llvmPackages.libclang
            llvmPackages.clang
            pkg-config
            openssl
            qemu
            rocksdb
          ];

          text = ''
            set -euo pipefail

            usage() {
              cat <<'USAGE'
            PhotonCloud local CI gates (provider-agnostic)

            Usage:
              photoncloud-gate [--tier 0|1|2] [--workspace <name>] [--shared-crates] [--shared-crate <name>] [--no-logs] [--fix]

            Tiers:
              0: fmt + clippy + unit tests (lib)   (fast, stable default)
              1: tier0 + integration tests (--tests)
              2: tier1 + ignored tests (-- --ignored)

            Notes:
              - Requires running inside a git checkout (uses `git rev-parse`).
              - Logs are written to ./work/ci/<timestamp>/ by default (NOT .cccc/).
              - Supported workspaces: ${supportedWorkspaces}
            USAGE
            }

            tier="0"
            only_ws=""
            shared_crates="0"
            only_shared_crate=""
            no_logs="0"
            fix="0"

            while [[ $# -gt 0 ]]; do
              case "$1" in
                --tier)
                  tier="$2"; shift 2;;
                --workspace)
                  only_ws="$2"; shift 2;;
                --shared-crates)
                  shared_crates="1"; shift 1;;
                --shared-crate)
                  only_shared_crate="$2"; shift 2;;
                --no-logs)
                  no_logs="1"; shift 1;;
                --fix)
                  fix="1"; shift 1;;
                -h|--help)
                  usage; exit 0;;
                *)
                  echo "[gate] ERROR: unknown arg: $1" >&2
                  usage
                  exit 2
                  ;;
              esac
            done

            if [[ "$tier" != "0" && "$tier" != "1" && "$tier" != "2" ]]; then
              echo "[gate] ERROR: --tier must be 0, 1, or 2 (got: $tier)" >&2
              exit 2
            fi

            repo_root="$(git rev-parse --show-toplevel)"

            # Avoid .cccc/ (managed externally). Use work/ for local artifacts.
            timestamp="$(date -u +%Y%m%d-%H%M%S)"
            logdir="$repo_root/work/ci/$timestamp"

            if [[ "$no_logs" == "0" ]]; then
              mkdir -p "$logdir"
              echo "[gate] logs: $logdir"
            else
              echo "[gate] logs: disabled"
            fi

            # Prefer Nix-provided toolchain over user's ~/.cargo binaries.
            #
            # `nix run` keeps the user's PATH (often including ~/.cargo/bin), which can cause
            # cargo subcommands (cargo-fmt, etc.) to resolve outside Nix.
            # Force PATH to Nix-provided tools only.
            export PATH="${pkgs.lib.makeBinPath [
              pkgs.bash
              pkgs.coreutils
              pkgs.findutils
              pkgs.gnugrep
              pkgs.gawk
              pkgs.git
              pkgs.jq
              rustToolchain
              rustfmtComponent
              clippyComponent
              pkgs.protobuf
              pkgs.llvmPackages.libclang
              pkgs.llvmPackages.clang
              pkgs.pkg-config
              pkgs.openssl
              pkgs.qemu
            ]}"

            CARGO="${rustToolchain}/bin/cargo"
            export RUSTC="${rustToolchain}/bin/rustc"
            CARGO_FMT="${rustToolchain}/bin/cargo-fmt"
            CARGO_CLIPPY="${rustToolchain}/bin/cargo-clippy"

            fmt_rustfmt_args="-- --check"
            if [[ "$fix" == "1" ]]; then
              fmt_rustfmt_args=""
            fi

            export LIBCLANG_PATH="${pkgs.llvmPackages.libclang.lib}/lib";
            export PROTOC="${pkgs.protobuf}/bin/protoc"
            export ROCKSDB_LIB_DIR="${pkgs.rocksdb}/lib"
            export CARGO_TARGET_DIR="$repo_root/work/cargo-target"
            mkdir -p "$CARGO_TARGET_DIR"

            manifest_has_target_kind() {
              local manifest="$1"; shift
              local kind="$1"; shift

              "$CARGO" metadata --format-version 1 --no-deps --manifest-path "$manifest" \
                | jq -e --arg kind "$kind" 'any(.packages[]?.targets[]?.kind[]?; . == $kind)' > /dev/null
            }

            run_cmd() {
              local ws="$1"; shift
              local title="$1"; shift
              local cmd="$*"

              echo ""
              echo "================================================================================"
              echo "[gate][$ws] $title"
              echo "--------------------------------------------------------------------------------"
              echo "[gate][$ws] $cmd"
              echo "================================================================================"

              if [[ "$no_logs" == "0" ]]; then
                local out
                out="$logdir/$ws.$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '_' | tr -cd 'a-z0-9_').log"
                (cd "$repo_root/$ws" && bash -c "$cmd") 2>&1 | tee "$out"
              else
                (cd "$repo_root/$ws" && bash -c "$cmd")
              fi
            }

            run_shared_crate_cmd() {
              local crate="$1"; shift
              local manifest="$1"; shift
              local title="$1"; shift
              local cmd="$*"

              echo ""
              echo "================================================================================"
              echo "[gate][shared:$crate] $title"
              echo "--------------------------------------------------------------------------------"
              echo "[gate][shared:$crate] $cmd"
              echo "================================================================================"

              if [[ "$no_logs" == "0" ]]; then
                local out
                out="$logdir/shared_''${crate}.$(echo "$title" | tr '[:upper:]' '[:lower:]' | tr ' ' '_' | tr -cd 'a-z0-9_').log"
                (cd "$repo_root" && bash -c "$cmd") 2>&1 | tee "$out"
              else
                (cd "$repo_root" && bash -c "$cmd")
              fi
            }

            run_shared_crate_clippy() {
              local crate="$1"; shift
              local manifest="$1"; shift
              local ran_clippy="0"

              if manifest_has_target_kind "$manifest" "lib"; then
                run_shared_crate_cmd "$crate" "$manifest" "clippy (lib)" "$CARGO_CLIPPY clippy --manifest-path \"$manifest\" --lib -- -D warnings"
                ran_clippy="1"
              fi
              if manifest_has_target_kind "$manifest" "bin"; then
                run_shared_crate_cmd "$crate" "$manifest" "clippy (bin)" "$CARGO_CLIPPY clippy --manifest-path \"$manifest\" --bins -- -D warnings"
                ran_clippy="1"
              fi
              if [[ "$ran_clippy" == "0" ]]; then
                echo "[gate][shared:$crate] WARN: no lib/bin targets for clippy"
              fi
            }

            run_workspace_clippy() {
              local ws="$1"; shift
              local manifest="$1"; shift
              local ran_clippy="0"

              if manifest_has_target_kind "$manifest" "lib"; then
                run_cmd "$ws" "clippy (lib)" "$CARGO_CLIPPY clippy --workspace --lib -- -D warnings"
                ran_clippy="1"
              fi
              if manifest_has_target_kind "$manifest" "bin"; then
                run_cmd "$ws" "clippy (bin)" "$CARGO_CLIPPY clippy --workspace --bins -- -D warnings"
                ran_clippy="1"
              fi
              if [[ "$ran_clippy" == "0" ]]; then
                echo "[gate][$ws] WARN: no lib/bin targets for clippy"
              fi
            }

            run_shared_crates() {
              local only_crate="$1"
              local manifests=()
              local selected_count=0
              while IFS= read -r manifest; do
                manifests+=("$manifest")
              done < <(find "$repo_root/crates" -mindepth 2 -maxdepth 2 -name Cargo.toml | sort)

              if [[ "''${#manifests[@]}" -eq 0 ]]; then
                echo "[gate] WARN: no shared crate manifests found under crates/"
                return 0
              fi

              for manifest in "''${manifests[@]}"; do
                local crate
                local ran_unit_tests
                crate="$(basename "$(dirname "$manifest")")"
                if [[ -n "$only_crate" && "$crate" != "$only_crate" ]]; then
                  continue
                fi
                selected_count=$((selected_count + 1))
                run_shared_crate_cmd "$crate" "$manifest" "fmt" "$CARGO_FMT fmt --manifest-path \"$manifest\" $fmt_rustfmt_args"
                run_shared_crate_clippy "$crate" "$manifest"
                ran_unit_tests="0"
                if manifest_has_target_kind "$manifest" "lib"; then
                  run_shared_crate_cmd "$crate" "$manifest" "test (tier0 unit lib)" "$CARGO test --manifest-path \"$manifest\" --lib"
                  ran_unit_tests="1"
                fi
                if manifest_has_target_kind "$manifest" "bin"; then
                  run_shared_crate_cmd "$crate" "$manifest" "test (tier0 unit bin)" "$CARGO test --manifest-path \"$manifest\" --bins"
                  ran_unit_tests="1"
                fi
                if [[ "$ran_unit_tests" == "0" ]]; then
                  echo "[gate][shared:$crate] WARN: no lib/bin unit test targets"
                fi

                if [[ "$tier" == "1" || "$tier" == "2" ]]; then
                  run_shared_crate_cmd "$crate" "$manifest" "test (tier1 integration)" "$CARGO test --manifest-path \"$manifest\" --tests"
                fi

                if [[ "$tier" == "2" ]]; then
                  run_shared_crate_cmd "$crate" "$manifest" "test (tier2 ignored)" "$CARGO test --manifest-path \"$manifest\" --tests -- --ignored"
                fi
              done

              if [[ -n "$only_crate" && "$selected_count" -eq 0 ]]; then
                echo "[gate] ERROR: shared crate not found: $only_crate" >&2
                exit 2
              fi
            }

            if [[ "$shared_crates" == "1" ]]; then
              run_shared_crates "$only_shared_crate"
              echo ""
              echo "[gate] OK (tier=$tier, shared-crates)"
              exit 0
            fi

            if [[ -n "$only_shared_crate" ]]; then
              run_shared_crates "$only_shared_crate"
              echo ""
              echo "[gate] OK (tier=$tier, shared-crates)"
              exit 0
            fi

            for ws in ${pkgs.lib.concatStringsSep " " wsList}; do
              if [[ -n "$only_ws" && "$only_ws" != "$ws" ]]; then
                continue
              fi

              if [[ ! -f "$repo_root/$ws/Cargo.toml" ]]; then
                echo "[gate] WARN: skipping $ws (no Cargo.toml)"
                continue
              fi

              workspace_manifest="$repo_root/$ws/Cargo.toml"

              # Format gate: call Nix-provided `cargo-fmt` directly (avoid resolving ~/.cargo/bin/cargo-fmt).
              #
              # NOTE: Avoid `--all` here; with path-dependencies it may traverse outside the workspace directory.
              run_cmd "$ws" "fmt" "$CARGO_FMT fmt $fmt_rustfmt_args"
              # Tier0 clippy stays on lib/bin targets to avoid dragging in
              # heavy integration-only dev-dependencies for every workspace.
              run_workspace_clippy "$ws" "$workspace_manifest"
              ran_unit_tests="0"
              if manifest_has_target_kind "$workspace_manifest" "lib"; then
                run_cmd "$ws" "test (tier0 unit lib)" "$CARGO test --workspace --lib"
                ran_unit_tests="1"
              fi
              if manifest_has_target_kind "$workspace_manifest" "bin"; then
                run_cmd "$ws" "test (tier0 unit bin)" "$CARGO test --workspace --bins"
                ran_unit_tests="1"
              fi
              if [[ "$ran_unit_tests" == "0" ]]; then
                echo "[gate][$ws] WARN: no lib/bin unit test targets"
              fi

              if [[ "$tier" == "1" || "$tier" == "2" ]]; then
                run_cmd "$ws" "test (tier1 integration)" "$CARGO test --workspace --tests"
              fi

              if [[ "$tier" == "2" ]]; then
                run_cmd "$ws" "test (tier2 ignored)" "$CARGO test --workspace --tests -- --ignored"
              fi
            done

            echo ""
            echo "[gate] OK (tier=$tier)"
          '';
        };
      in
      {
        packages.gate = gate;

        apps.gate = flake-utils.lib.mkApp {
          drv = gate;
        };

        # CI-optimized gate (alias)
        packages.gate-ci = gate;

        # Checks are minimal and mirror tier0 (provider-agnostic).
        checks.gate-tier0 = pkgs.runCommand "photoncloud-gate-tier0" { } ''
          mkdir -p $out
          ${gate}/bin/photoncloud-gate --tier 0 --no-logs
          touch $out/ok
        '';
        checks.deployer-vm-smoke = photoncloud.checks.${system}.deployer-vm-smoke;
        checks.deployer-vm-rollback = photoncloud.checks.${system}.deployer-vm-rollback;
        checks.deployer-bootstrap-e2e = photoncloud.checks.${system}.deployer-bootstrap-e2e;
        checks.host-lifecycle-e2e = photoncloud.checks.${system}.host-lifecycle-e2e;
        checks.fleet-scheduler-e2e = photoncloud.checks.${system}.fleet-scheduler-e2e;

        devShells.default = pkgs.mkShell {
          name = "photoncloud-ci-dev";
          buildInputs = with pkgs; [
            rustToolchain
            protobuf
            llvmPackages.libclang
            llvmPackages.clang
            pkg-config
            openssl
            rocksdb
            git
          ];
          LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
          PROTOC = "${pkgs.protobuf}/bin/protoc";
          ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib";
        };
      }
    );
}
