export interface Position {
	/** 0-based line number. */
	line: number;
	/** 0-based UTF-16 code-unit offset from the line start, matching LSP. */
	character: number;
}

export interface Range {
	start: Position;
	end: Position;
}

export interface TextEdit {
	range: Range;
	newText: string;
}

export interface ApplyEditsOptions {
	/** fsync the temp file and parent directory before/after rename. Defaults to true. */
	fsync?: boolean;
}

export interface ApplyEditsResult {
	editsApplied: number;
	bytesWritten: number;
}

export interface TextDocumentEdit {
	filePath: string;
	edits: TextEdit[];
}

export interface WorkspaceEditLike {
	documentChanges?: TextDocumentEdit[];
	changes?: Record<string, TextEdit[]>;
}

export interface WorkspaceEditFileResult {
	filePath: string;
	editsApplied: number;
	bytesWritten: number;
}

export interface ApplyWorkspaceEditResult {
	filesChanged: number;
	totalEditsApplied: number;
	files: WorkspaceEditFileResult[];
}

export interface ReplaceSymbolOptions {
	/** Force a specific language. If absent, inferred from the file extension. */
	lang?: string;
	/** fsync the write. Defaults to true. */
	fsync?: boolean;
}

export interface ReplaceSymbolResult {
	matched: boolean;
	byteStart?: number;
	byteEnd?: number;
	startLine?: number;
}

export type InsertPosition =
	| "BeforeDecl"
	| "AfterDecl"
	| "AtBodyStart"
	| "AtBodyEnd";

export interface InsertAroundSymbolOptions {
	/** Force a specific language. If absent, inferred from the file extension. */
	lang?: string;
	/** fsync the write. Defaults to true. */
	fsync?: boolean;
}

export interface InsertAroundSymbolResult {
	inserted: boolean;
	byteOffset?: number;
}

export type WatchEventKind = "create" | "modify" | "remove" | "rename";

export interface WatchEvent {
	kind: WatchEventKind;
	path: string;
}

export interface WatchOptions {
	/** Glob patterns to ignore. Bare patterns match anywhere below the root. */
	ignore?: string[];
	/** Coalesce events that fire within this window in milliseconds. Defaults to 50. */
	debounceMs?: number;
	/** Watch recursively. Defaults to true. */
	recursive?: boolean;
}

export interface WatchHandle {
	stop(): void;
	on(event: "events", listener: (events: WatchEvent[]) => void): this;
}
