import type { Component, RootBoundaryOptions } from '#public';

// Re-export runtime types for server-compiled components
export {
	track,
	untrack,
	flushSync,
	effect,
	tick,
	Context,
	RippleArray,
	RippleSet,
	RippleMap,
	RippleDate,
	RippleURL,
	RippleURLSearchParams,
} from './index.js';

export interface RenderResult {
	head: string;
	body: string;
	css: Set<string>;
	topLevelError?: Error | null;
}

export interface RenderStreamResult {
	stream: StreamSink;
	topLevelError?: Error | null;
}

export interface StreamSink {
	push(chunk: string): void;
	close(): void;
	error(reason: unknown): void;
}

export type WebStream = ReadableStream<Uint8Array>;

export interface Stream {
	controller: ReadableStreamDefaultController<Uint8Array>;
	textEncoder: TextEncoder;
	stream: WebStream;
	sink: StreamSink;
}

export interface StreamTemplate {
	/** Document prefix, up to (and excluding) where SSR head content belongs. */
	before: string;
	/** From after the SSR head content to where the SSR body belongs. */
	between: string;
	/** Document suffix, pushed right before the stream closes. */
	after: string;
}

export interface BaseRenderOptions {
	stream?: StreamSink;
	// defaults to true
	// set to false to add more content
	closeStream?: boolean;
	rootBoundary?: RootBoundaryOptions;
	/**
	 * Streaming only: document scaffold emitted around the shell — `before` +
	 * head content + `between` + body precede the streamed chunks, `after` is
	 * pushed when the stream closes.
	 */
	streamTemplate?: StreamTemplate;
}

export interface StreamingRenderOptions extends BaseRenderOptions {
	stream: StreamSink;
}

export interface RenderOptions extends BaseRenderOptions {
	stream?: undefined;
}

export declare function createStream(): Stream;

/**
 * Returns the CSS text for a set of scoped style hashes collected by
 * `render()` — emit it in a `<style data-ripple-ssr>` tag.
 */
export declare function getCss(css: Set<string>): string;

export declare function render(
	component: Component,
	options?: RenderOptions,
): Promise<RenderResult>;

export declare function render(
	component: Component,
	options: StreamingRenderOptions,
): Promise<RenderStreamResult>;
