import { AikitConfig, IndexStats } from "../../core/dist/index.js";
import { GraphEdge, GraphNode, IGraphStore, IKnowledgeStore } from "../../store/dist/index.js";
import { IEmbedder } from "../../embeddings/dist/index.js";

//#region packages/indexer/src/file-hasher.d.ts
/**
 * Generate a deterministic hash for a file's content.
 * Used for incremental indexing -- skip files that haven't changed.
 */
declare function hashContent(content: string): string;
/**
 * Generate a deterministic ID for a knowledge record.
 * Based on source path + chunk index to ensure idempotent upserts.
 */
declare function generateRecordId(sourcePath: string, chunkIndex: number): string;
//#endregion
//#region packages/indexer/src/filesystem-crawler.d.ts
interface CrawlResult {
  /** File path relative to workspace root */
  relativePath: string;
  /** Absolute file path */
  absolutePath: string;
  /** File extension (lowercase, with dot) */
  extension: string;
  /** File size in bytes */
  size: number;
  /** Last modified time in milliseconds since epoch */
  mtimeMs: number;
  /** Lazily read file content when downstream processing actually needs it. */
  readContent: () => Promise<string>;
  /** Cached file content after the first read. */
  content?: string;
}
interface CrawlOptions {
  /** Glob patterns to exclude */
  excludePatterns: string[];
  /** Root directory to crawl */
  rootDir: string;
}
/**
 * Crawl a directory tree and yield files that should be indexed.
 */
declare class FilesystemCrawler {
  /** Binary file extensions that should always be skipped */
  private static readonly BINARY_EXTENSIONS;
  private static readonly GENERATED_PATH_PATTERN;
  private static readonly GENERATED_SAMPLE_LIMIT;
  crawl(options: CrawlOptions): Promise<CrawlResult[]>;
  private walkDir;
  private isExcluded;
  static isLikelyGeneratedPath(relativePath: string): boolean;
  static isLikelyGeneratedContent(content: string, relativePath: string, _size: number): boolean;
  private static readTextPreview;
}
//#endregion
//#region packages/indexer/src/graph-extractor.d.ts
interface ExtractGraphOptions {
  /** Maps workspace package names to entry module paths without extensions. */
  workspacePackages?: Map<string, string>;
}
interface ExtractedGraph {
  nodes: GraphNode[];
  edges: GraphEdge[];
}
/**
 * Extract graph nodes and edges from a single file's content.
 * Produces:
 * - One "module" node per file
 * - Symbol nodes (function, class, interface, type, const, enum)
 * - "defines" edges from module → symbol
 * - "imports" edges from module → imported module
 */
declare function extractGraph(content: string, sourcePath: string, options?: ExtractGraphOptions): ExtractedGraph;
//#endregion
//#region packages/indexer/src/hash-cache.d.ts
/**
 * Persistent file hash cache.
 * Stores path->hash + metadata mappings in a JSON file to avoid repeated
 * content reads and LanceDB round-trips when checking which files changed.
 */
interface FileHashCacheEntry {
  hash: string;
  size?: number;
  mtimeMs?: number;
}
declare class FileHashCache {
  private cache;
  private readonly filePath;
  private dirty;
  constructor(storeDir: string);
  /** Load cache from disk. Non-fatal if missing or corrupt. */
  load(): void;
  get(path: string): string | undefined;
  getEntry(path: string): FileHashCacheEntry | undefined;
  set(path: string, hash: string, metadata?: {
    size: number;
    mtimeMs: number;
  }): void;
  delete(path: string): void;
  /** Persist cache to disk if changed. */
  flush(): void;
  /** Clear all entries and delete file. */
  clear(): void;
  get size(): number;
}
//#endregion
//#region packages/indexer/src/incremental-indexer.d.ts
interface IndexProgress {
  phase: 'crawling' | 'chunking' | 'embedding' | 'storing' | 'cleanup' | 'done';
  filesTotal: number;
  filesProcessed: number;
  chunksTotal: number;
  chunksProcessed: number;
  /** The file currently being processed */
  currentFile?: string;
}
type ProgressCallback = (progress: IndexProgress) => void;
interface IndexResult {
  filesProcessed: number;
  filesSkipped: number;
  chunksCreated: number;
  chunksDeduped: number;
  filesRemoved: number;
  durationMs: number;
}
declare class IncrementalIndexer {
  private readonly embedder;
  private readonly store;
  private readonly crawler;
  private indexing;
  private graphStore?;
  private hashCache?;
  /** Whether an index operation is currently in progress. */
  get isIndexing(): boolean;
  constructor(embedder: IEmbedder, store: IKnowledgeStore);
  /**
   * Normalize chunk text for content-based dedup hashing.
   * Strips the file path header, lowercases, collapses whitespace.
   * Modular — swap this to change dedup normalization strategy.
   */
  private normalizeChunkText;
  private loadFileContent;
  private isMetadataUnchanged;
  /** Set the graph store for auto-population during indexing and cleanup on re-index. */
  setGraphStore(graphStore: IGraphStore): void;
  /** Set the hash cache for faster incremental checks. */
  setHashCache(cache: FileHashCache): void;
  /**
   * Index all configured sources. Only re-indexes files that have changed.
   * Sources are crawled in parallel, and file processing runs concurrently
   * up to `config.indexing.concurrency` (default: 50% of CPU cores, minimum 2, maximum 4).
   */
  index(config: AikitConfig, onProgress?: ProgressCallback): Promise<IndexResult>;
  /**
   * Crawl sources and return file paths whose content has changed since the last index.
   * This performs a read-only scan and does not modify the store.
   */
  getChangedFiles(config: AikitConfig): Promise<string[]>;
  /**
   * Index only the specified file paths.
   * Files that have not changed are skipped.
   */
  indexFiles(config: AikitConfig, paths: string[], onProgress?: ProgressCallback): Promise<IndexResult>;
  private doIndex;
  private doIndexFiles;
  private crawlSources;
  private planIndexWork;
  private getPathsToRemove;
  private buildWorkspacePackageMap;
  private processFiles;
  private cleanupRemovedFiles;
  /**
   * Force re-index all files (ignoring hashes).
   */
  reindexAll(config: AikitConfig, onProgress?: ProgressCallback): Promise<IndexResult>;
  private doReindex;
  /**
   * Get current index statistics.
   */
  getStats(): Promise<IndexStats>;
}
//#endregion
//#region packages/indexer/src/smart-index-scheduler.d.ts
/**
 * SmartIndexScheduler trickles indexing work over time instead of running
 * large idle-triggered indexing passes.
 */
declare class SmartIndexScheduler {
  private readonly indexer;
  private readonly config;
  private readonly store?;
  private trickleTimer;
  private stopped;
  private readonly trickleIntervalMs;
  private readonly batchSize;
  private readonly priorityQueue;
  private changedFiles;
  private lastRefreshTime;
  private refreshing;
  constructor(indexer: IncrementalIndexer, config: AikitConfig, store?: {
    createFtsIndex: () => Promise<void>;
  } | undefined);
  /** Start the trickle indexing loop. */
  start(): void;
  /** Stop the scheduler and clear all timers. */
  stop(): void;
  /**
   * Add file paths to the front of the priority queue for near-term indexing.
   */
  prioritize(...paths: string[]): void;
  getState(): {
    mode: 'smart';
    queueSize: number;
    changedFilesSize: number;
    intervalMs: number;
    batchSize: number;
    running: boolean;
  };
  private readPositiveIntEnv;
  private scheduleTick;
  private tick;
  private getCpuCount;
  private pickFiles;
  private maybeRefreshChangedFiles;
}
//#endregion
export { type CrawlOptions, type CrawlResult, type ExtractGraphOptions, type ExtractedGraph, FileHashCache, FilesystemCrawler, IncrementalIndexer, type IndexProgress, type IndexResult, type ProgressCallback, SmartIndexScheduler, extractGraph, generateRecordId, hashContent };