import type { Readable } from "node:stream";
import type {
  Worker,
  Serializable as WorkerSerializable,
} from "node:worker_threads";
import type React from "react";
// React types are imported from vendor system at runtime
import type {
  NormalizedOutputOptions,
  OutputBundle,
  PreRenderedAsset,
  PreRenderedChunk,
} from "rollup";
import type { PassThrough, Transform } from "stream";
import type {
  AliasOptions,
  BuildOptions,
  Connect,
  Logger,
  Manifest,
  Plugin,
  ResolveOptions,
  UserConfig,
  ViteDevServer,
} from "vite";
import type {
  serializeResolvedConfig,
  serializeResolvedUserConfig,
} from "./helpers/serializeUserOptions.js";
import type { AllowedDirectives, Program } from "react-server-loader/directives";
import type { LoaderConfig, TransformOptions } from "./loader/types.js";
import type {
  RenderMetrics,
  StreamMetrics,
  WorkerStartupMetrics,
  ModuleResolutionMetrics,
} from "./metrics/types.js";
import type { HtmlWorkerOutputMessage } from "./worker/html/types.js";
import type { RscChunkOutputMessage } from "./worker/rsc/types.js";
import type { WorkerMessage } from "./worker/types.js";
import type { Strategy } from "./orchestrator/createPluginOrchestrator.server.js";
import type { RenderToPipeableStreamOptions as ClientRenderToPipeableStreamOptions } from "react-dom/server";
import type { RenderToPipeableStreamOptions as ServerRenderToPipeableStreamOptions } from "react-server-dom-esm/server.node";

export type OnEvent<
  Interface extends ViteReactServerComponentsPlugin = ViteReactServerComponentsPlugin
> = (event: PluginEvent<Interface>) => void;

export type OnMetrics = (
  metrics:
    | RenderMetrics<"rsc-full" | "rsc-headless" | "html">
    | WorkerStartupMetrics
    | ModuleResolutionMetrics
) => void;

export type MessageHandler<
  T extends HtmlWorkerOutputMessage | RscChunkOutputMessage =
    | HtmlWorkerOutputMessage
    | RscChunkOutputMessage
> = (message: T) => void | Promise<unknown>;

export type CreateInputNormalizerProps = {
  root: string;
  preserveModulesRoot?: string | undefined;
  removeExtension?: boolean | RegExp | string | ((path: string) => boolean);
  moduleBasePath: string | undefined;
  moduleBaseURL: string | undefined;
};
export type Serializable =
  | WorkerSerializable
  | Serializable[]
  | SerializableRecord;

export type SerializableRecord = {
  [key: string]: Serializable;
};

// Track HMR state
export type HmrState = {
  timestamp: number;
  invalidated: boolean;
  routes: string[];
};

export type RenderPageResult =
  | {
      type: "skip";
      reason?: unknown;
      html: {
        abort: (reason?: unknown) => void;
        pipe: <Writable extends NodeJS.WritableStream>(
          destination: Writable
        ) => Writable;
      };
      rsc: {
        abort: (reason?: unknown) => void;
        pipe: <Writable extends NodeJS.WritableStream>(
          destination: Writable
        ) => Writable;
      };
      metrics: {
        rscFull: RenderMetrics & { type: "rsc-full" };
        rscHeadless: RenderMetrics & { type: "rsc-headless" };
        html: RenderMetrics & { type: "html" };
      };
    }
  | {
      type: "error";
      error: unknown;
      metrics: {
        rscFull: RenderMetrics & { type: "rsc-full" };
        rscHeadless: RenderMetrics & { type: "rsc-headless" };
        html: RenderMetrics & { type: "html" };
      };
    }
  | {
      type: "success";
      html: {
        abort: (reason?: unknown) => void;
        pipe: <Writable extends NodeJS.WritableStream>(
          destination: Writable
        ) => Writable;
      };
      rsc: {
        abort: (reason?: unknown) => void;
        pipe: <Writable extends NodeJS.WritableStream>(
          destination: Writable
        ) => Writable;
      };
      metrics: {
        rscFull: RenderMetrics & { type: "rsc-full" };
        rscHeadless: RenderMetrics & { type: "rsc-headless" };
        html: RenderMetrics & { type: "html" };
      };
    };

export type AutoDiscoveredFiles = ResolvedBuildPages & {
  workerPaths: Record<string, string>;
  serverEntry: Record<string, string> | null;
  clientEntry: Record<string, string>;
  clientInputs: Record<string, string>;
  staticInputs: Record<string, string>;
  serverInputs: Record<string, string>;
  serverActions: Record<string, string>;
};

// Input can be a string path, React component, tuple, or array
export type NormalizerInput = unknown;

export type InputNormalizer = (input: NormalizerInput) => [string, string];

export type HtmlContent = {
  raw: string;
  transformed?: string;
  assets?: string[];
};

export type PartialPageData = {
  route: string;
  html?: {
    raw: string;
    transformed?: string;
    assets?: string[];
  };
  rsc?: {
    modules: unknown[];
    content: string;
  };
};

export type InputNormalizerWorker = (
  input: NormalizerInput
) => Promise<[string, string]>;

export type ResolvedUserConfig = Required<
  Pick<UserConfig, "root" | "mode" | "build" | "resolve">
> &
  Omit<UserConfig, "root" | "mode" | "build" | "resolve"> & {
    resolve: ResolveOptions;
  } & {
    build: NonNullable<
      Required<
        Pick<
          BuildOptions,
          | "target"
          | "outDir"
          | "assetsDir"
          | "ssr"
          | "ssrEmitAssets"
          | "ssrManifest"
          | "manifest"
          | "rollupOptions"
          | "modulePreload"
        >
      >
    > &
      Omit<
        BuildOptions,
        | "target"
        | "outDir"
        | "assetsDir"
        | "ssr"
        | "ssrEmitAssets"
        | "ssrManifest"
        | "manifest"
      >;
  };

export type SerializedUserConfig<
  T extends ResolvedUserConfig = ResolvedUserConfig
> = ReturnType<typeof serializeResolvedUserConfig<T>>;

export type SerializedUserOptions = {
  [k in keyof ResolvedUserOptions]: Extract<
    ResolvedUserOptions[k],
    Serializable | Record<string, Serializable>
  > extends infer X
    ? X extends never
      ? undefined
      : X
    : undefined;
};

export type SerializedResolvedConfig = ReturnType<
  typeof serializeResolvedConfig
>;

// Client plugin options
export type StreamPluginOptionsClient = {
  outDir?: string;
  build?: BuildConfig;
  assetsDir?: string;
  projectRoot?: string;
  moduleBase?: string;
  moduleBasePath?: string;
  moduleBaseURL?: string;
  clientComponents?: AliasOptions;
  cssFiles?: AliasOptions;
};

export type StringKeys =
  | "moduleBase"
  | "moduleBasePath"
  | "moduleBaseURL"
  | "moduleRootPath"
  | "projectRoot"
  | "pageExportName"
  | "propsExportName"
  | "htmlWorkerPath"
  | "rscWorkerPath"
  | "loaderPath"
  | "reactLoaderPath"
  | "cssLoaderPath"
  | "envLoaderPath"
  | "clientEntry"
  | "serverEntry"
  | "publicOrigin";

export type NumberKeys =
  | "rscTimeout"
  | "htmlTimeout"
  | "htmlWorkerStartupTimeout"
  | "rscWorkerStartupTimeout"
  | "fileWriteTimeout"
  | "workerShutdownTimeout";

export type BooleanKeys = "verbose";

export type NestedConfigKeys =
  | "build"
  | "autoDiscover"
  | "loader"
  | "css"
  | "pipeableStreamOptions"
  | "serverPipeableStreamOptions"
  | "clientPipeableStreamOptions";

export type EventKeys = "onMetrics" | "onEvent";

export type NormalizerKeys = "normalizer" | "moduleID";

export type ComponentKeys = "Html" | "Root";

export type SourceURLKeys = "Page" | "props";

export type OptKey =
  | StringKeys
  | NumberKeys
  | BooleanKeys
  | EventKeys
  | NormalizerKeys
  | ComponentKeys
  | SourceURLKeys;

export type AutoDiscoverConfig = {
  clientEntry: string;
  serverEntry: string;
  cssEntry: string;
  jsonEntry: string;
  htmlEntry: string;
  modulePattern: RegExp;
  serverPattern: RegExp;
  clientPattern: RegExp;
  pagePattern: RegExp;
  propsPattern: RegExp;
  cssPattern: RegExp;
  jsonPattern: RegExp;
  htmlPattern: RegExp;
  cssModulePattern: RegExp;
  vendorPattern: RegExp;
  nodePattern: RegExp;
  dotPattern: RegExp;
  virtualPattern: RegExp;
  rscPattern: RegExp;
};

export type GenericModuleLoader = (
  id: string
) => Promise<Record<string, unknown>>;

export type BuildModuleLoader<
  Opt extends Pick<
    ResolvedUserOptions,
    "pageExportName" | "propsExportName"
  > = Pick<ResolvedUserOptions, "pageExportName" | "propsExportName">,
  T extends PagePropOpt = PagePropOpt
> = <
  STR extends string,
  ID extends string = STR extends `${infer I extends string}${string}${string}`
    ? I
    : never,
  Special extends "?" | "#" | "" = STR extends `${string}${infer X extends
    | "?"
    | "#"}${string}`
    ? X
    : "",
  Extra extends string = STR extends `${string}${string}${infer Y extends string}`
    ? Y
    : ""
>(
  moduleId: STR
) => Promise<
  STR extends `${ID}${Special}${Extra}`
    ? `${Special}${Extra}` extends "?inline"
      ? { default: string }
      : Extra extends Opt["pageExportName"]
      ? {
          [k in Extra]: (props: T) => unknown;
        }
      : Extra extends Opt["propsExportName"]
      ? {
          [k in Extra]: T;
        }
      : Extra extends string
      ? Special extends "#"
        ? { [k in Extra]: unknown }
        : Record<string, unknown>
      : Record<string, unknown>
    : Record<string, unknown>
>;

// Interface-aware version of BuildModuleLoader
export type InterfaceAwareBuildModuleLoader<
  Interface extends ViteReactServerComponentsPlugin = DefaultInterface,
  Opt extends Pick<
    ResolvedUserOptions,
    "pageExportName" | "propsExportName"
  > = Pick<ResolvedUserOptions, "pageExportName" | "propsExportName">
> = BuildModuleLoader<Opt, Interface["PageProps"]>;

export type StreamError = {
  code?: string;
} & Error;

export type PanicThreshold = "none" | "critical_errors" | "all_errors";

export type ResolvedUserOptions = {
  // Core required properties
  projectRoot: string;
  moduleBase: string;
  moduleBasePath: string;
  moduleBaseURL: string;
  moduleRootPath: string;
  publicOrigin: string;
  pageExportName: string;
  propsExportName: string;
  htmlExportName: string;
  rootExportName: string;
  htmlWorkerPath: string;
  rscWorkerPath: string;
  loaderPath: string;
  reactLoaderPath?: string;
  cssLoaderPath?: string;
  envLoaderPath?: string;
  verbose: boolean;
  rscTimeout: number;
  htmlTimeout: number;
  htmlWorkerStartupTimeout: number;
  rscWorkerStartupTimeout: number;
  fileWriteTimeout: number;
  workerShutdownTimeout: number;
  panicThreshold: PanicThreshold;
  availableEnvironments?: string[];
  strategy?: Strategy;

  // Optional properties
  onEvent?: OnEvent<ViteReactServerComponentsPlugin> | undefined;
  props?: StreamPluginOptions["props"];
  clientEntry?: string;
  serverEntry?: string;
  /**
   * Packages whose internal `"use client"` per-file directives should be
   * honored by the RSC pipeline (Chakra UI, MUI, Mantine, react-aria, …).
   * When set, the matching node_modules paths bypass the transformer's
   * node_modules early-return, get added to `optimizeDeps.exclude` so esbuild
   * doesn't strip directives, and get added to `resolve.noExternal` so they
   * land in the server bundle where the transform actually runs.
   */
  clientPackages?: readonly string[];

  // Required complex properties
  Page: StreamPluginOptions["Page"];
  Html: StreamPluginOptions["Html"]; // Unresolved: can be string, function
  Root: StreamPluginOptions["Root"]; // Unresolved: can be string, function
  normalizer: InputNormalizer;
  moduleID:
    | ((
        id: string,
        sourceContent?: string,
        isClientByDirective?: boolean
      ) => string)
    | undefined;
  onMetrics: OnMetrics | undefined;
  // different for client/server so can't be typed
  pipeableStreamOptions: any;
  // Separate pipeable stream options for different environments
  serverPipeableStreamOptions?: any; // For dev server and RSC worker
  clientPipeableStreamOptions?: any; // For HTML worker
  autoDiscover: Required<AutoDiscoverConfig>;
  loader?: Required<LoaderConfig> | undefined;
  build: Required<BuildConfig>;
  dev: Required<DevConfig>;
  css: RootOptions<boolean>;
  components?: StreamPluginOptions["components"]; // Direct component overrides (optional)
};

export type DirectiveOptions = Pick<
  TransformOptions,
  "verbose" | "panicThreshold" | "loader"
> & {
  loader: Pick<
    Required<NonNullable<TransformOptions["loader"]>>,
    | "isServerFunctionCode"
    | "isClientComponentCode"
    | "getDirectiveType"
    | "parse"
  > & {
    allowedDirectives: AllowedDirectives;
  };
  logger?: Logger;
};

export type RootOptions<InlineCSS extends InlineCssOpt = InlineCssOpt> = {
  inlineCss?: InlineCSS;
  inlineThreshold?: number;
  inlinePatterns?: RegExp[];
  linkPatterns?: RegExp[];
};

export type CssContent<InlineCSS extends InlineCssOpt = InlineCssOpt> =
  InlineCSS extends true
    ? StyleCssProps
    : InlineCSS extends false
    ? LinkCssProps
    : InlineCSS extends undefined | boolean
    ? StyleCssProps | LinkCssProps
    : never;

/**
 * Boxed component type for the Root
 */

export type CssComponentType<
  InlineCSS extends InlineCssOpt = InlineCssOpt,
  R = any
> = (props: {
  cssFiles: Map<string, CssContent<InlineCSS>> | CssContent[];
}) => R;

export type FileWriteEvent = {
  type: "file.write";
  data: {
    path: string;
    fileType: "html" | "rsc";
    route: string;
    stream: Readable;
    onComplete: () => Promise<void>;
  };
};

export type FileWriteDoneEvent = {
  type: "file.write.done";
  data: {
    route: string;
    fileType: "html" | "rsc";
    content: string;
    chunks: number;
    path: string;
    fileName: string;
    baseDir: string;
    routePath: string;
  };
};

export type RouteErrorEvent = {
  type: "route.error";
  data: {
    route: string;
    error?: unknown | null;
    errorInfo?: {
      componentStack?: string | null;
      digest?: string | null;
    };
    reason?: unknown;
    isPanic?: boolean;
    panicThreshold?: PanicThreshold;
  };
};

export type RouteShellErrorEvent = {
  type: "route.shellError";
  data: {
    route: string;
    error: unknown;
  };
};

export type RoutePostponeEvent = {
  type: "route.postpone";
  data: {
    route: string;
    reason?: unknown;
  };
};

export type RouteShellReadyEvent = {
  type: "route.shellReady";
  data: {
    route: string;
  };
};

export type RouteAllReadyEvent = {
  type: "route.allReady";
  data: {
    route: string;
  };
};

export type PropsLoadEvent = {
  type: "props.load";
  data: {
    route: string;
    propsPath: string;
    props: unknown;
  };
};

export type CssProcessEvent<
  Interface extends ViteReactServerComponentsPlugin = DefaultInterface
> = {
  type: "css.process";
  data: InterfaceAwareCssContent<Interface>;
};

export type BuildStartEvent = {
  type: "build.start";
  data: {
    pages: string[];
    files: AutoDiscoveredFiles;
  };
};

export type BuildWriteBundleEventServer = {
  type: "build.writeBundle.server";
  data: {
    pages: string[];
    options: NormalizedOutputOptions;
    bundle: OutputBundle;
  };
};

export type BuildWriteBundleEventClient = {
  type: "build.writeBundle.client";
  data: {
    pages: string[];
    options: NormalizedOutputOptions;
    bundle: OutputBundle;
  };
};

export type BuildWriteBundleEventStatic = {
  type: "build.writeBundle.static";
  data: {
    pages: string[];
    options: NormalizedOutputOptions;
    bundle: OutputBundle;
  };
};

export type BuildEventStaticSiteGenerationStart = {
  type: "build.ssg.start"; // SSG process starts (from client environment)
  data: {
    pages: string[];
    options: NormalizedOutputOptions;
    bundle: OutputBundle;
  };
};
export type BuildEventStaticSiteGenerationEnd = {
  type: "build.ssg.end"; // SSG process ends (from server environment)
  data: {
    pages: string[];
    options: NormalizedOutputOptions;
    bundle: OutputBundle;
  };
};

export type BuildWriteBundleEvent =
  | BuildWriteBundleEventServer
  | BuildWriteBundleEventClient
  | BuildEventStaticSiteGenerationStart
  | BuildEventStaticSiteGenerationEnd
  | BuildWriteBundleEventStatic;

export type PluginEvent<
  Interface extends ViteReactServerComponentsPlugin = ViteReactServerComponentsPlugin
> =
  | FileWriteEvent
  | FileWriteDoneEvent
  | RouteErrorEvent
  | RouteShellErrorEvent
  | RoutePostponeEvent
  | PropsLoadEvent
  | CssProcessEvent<Interface>
  | BuildStartEvent
  | BuildWriteBundleEvent
  | RouteShellReadyEvent
  | RouteAllReadyEvent;

export type PluginEventType = PluginEvent["type"];

export interface StreamPluginOptions<
  Interface extends ViteReactServerComponentsPlugin = DefaultInterface
> {
  projectRoot?: string; // defaults to process.cwd()
  moduleBase: string; // defaults to 'src'
  moduleBasePath?: string; // defaults to ''
  moduleBaseURL?: string; // defaults to '/'
  moduleRootPath?: string; // defaults to client's dist folder
  publicOrigin?: string; // defaults to window.location.origin in client & http://localhost:port in development
  clientEntry?: string;
  serverEntry?: string; // Loader configuration
  loader?: {
    importServerPath?: string;
    importClientPath?: string;
    registerClientReferenceName?: string;
    registerServerReferenceName?: string;
    serverDirective?: RegExpOpt;
    clientDirective?: RegExpOpt;
    directivePattern?: RegExpOpt;
    isServerFunctionCode?: (code: string, moduleId?: string) => boolean;
    isClientComponentCode?: (code: string, moduleId?: string) => boolean;
    isClientComponentByCode?: (code: string) => boolean;
    isClientComponentByName?: (moduleId: string) => boolean;
    moduleID?: (moduleId: string) => string;
    allowedDirectives?: string[] | AllowedDirectives;
    mode?: "development" | "production" | "test";
    getDirectiveType?: (
      directive: string,
      moduleId?: string
    ) => "client" | "server" | undefined;
    parse?: (source: string) => Promise<{
      ast: Program;
      code: string;
      map?: { url: string; start: number; end: number; lines: number } | null;
    }>;
  };
  // Auto-discovery (zero-config)
  autoDiscover?:
    | {
        clientEntry: string;
        serverEntry: string;
        cssEntry: string;
        jsonEntry: string;
        htmlEntry: string;
        // CSS related
        /**
         * Pattern to match CSS files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   cssPattern: ".css$",
         *   // Or RegExp pattern
         *   cssPattern: /\.css$/
         * }
         */
        cssPattern?: RegExpOpt;
        /**
         * Pattern to match CSS module files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   cssModulePattern: ".css\\.js$",
         *   // Or RegExp pattern
         *   cssModulePattern: /\.css\.js$/
         * }
         */
        cssModulePattern?: RegExpOpt;

        // Client/Server related
        /**
         * Pattern to match client component files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   clientPattern: ".client\\.(js|ts|jsx|tsx)$",
         *   // Or RegExp pattern
         *   clientPattern: /\.client\.(js|ts|jsx|tsx)$/
         * }
         */
        clientPattern?: RegExpOpt;
        /**
         * Pattern to match server function files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   serverPattern: ".server\\.(js|ts|jsx|tsx)$",
         *   // Or RegExp pattern
         *   serverPattern: /\.server\.(js|ts|jsx|tsx)$/
         * }
         */
        serverPattern?: RegExpOpt;

        // HTML related
        /**
         * Pattern to match HTML files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   htmlPattern: ".html$",
         *   // Or RegExp pattern
         *   htmlPattern: /\.html$/
         * }
         */
        htmlPattern?: RegExpOpt;

        // JSON related
        /**
         * Pattern to match JSON files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   jsonPattern: ".json$",
         *   // Or RegExp pattern
         *   jsonPattern: /\.json$/
         * }
         */
        jsonPattern?: RegExpOpt;

        // JS/Module related

        /**
         * Pattern to match module files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   modulePattern: "\\.(js|ts|jsx|tsx)$",
         *   // Or RegExp pattern
         *   modulePattern: /\.(js|ts|jsx|tsx)$/
         * }
         */
        modulePattern?: RegExpOpt;

        // RSC related
        /**
         * Pattern to match RSC files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   rscPattern: ".rsc$",
         *   // Or RegExp pattern
         *   rscPattern: /\.rsc$/
         * }
         */
        rscPattern?: RegExpOpt;

        // Page/Props related
        /**
         * Pattern to match page files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   pagePattern: "[Pp]age\\.(js|ts|jsx|tsx)$",
         *   // Or RegExp pattern
         *   pagePattern: /[Pp]age\.(js|ts|jsx|tsx)$/
         * }
         */
        pagePattern?: RegExpOpt;
        /**
         * Pattern to match props files. If not provided, uses default pattern.
         * Provide either a string pattern or RegExp.
         * @example ```ts
         * autoDiscover: {
         *   // String pattern
         *   propsPattern: "[Pp]rops\\.(js|ts|jsx|tsx)$",
         *   // Or RegExp pattern
         *   propsPattern: /[Pp]rops\.(js|ts|jsx|tsx)$/
         * }
         */
        propsPattern?: RegExpOpt;

        // Special patterns
        /**
         * Pattern to match dot files. No interpolation support.
         * @example ```ts
         * autoDiscover: {
         *   dotFiles: /^\.[^/]+$/
         * }
         */
        dotPattern?: RegExpOpt;
        /**
         * Pattern to match Node.js native modules. No interpolation support.
         * @example ```ts
         * autoDiscover: {
         *   nodePattern: /.node/
         * }
         */
        nodePattern?: RegExpOpt;
        /**
         * Pattern to match vendor files. No interpolation support.
         * @example ```ts
         * autoDiscover: {
         *   vendorPattern: /node_modules|_virtual/
         * }
         */
        vendorPattern?: RegExpOpt;
        /**
         * Pattern to match virtual files. No interpolation support.
         * @example ```ts
         * autoDiscover: {
         *   virtualPattern: /^virtual:/
         * }
         */
        virtualPattern?: RegExpOpt;
      }
    | undefined;
  // Manual configuration
  Page?: UrlOpt;
  props?: UrlOpt;
  // Escape hatches
  htmlWorkerPath?: string;
  rscWorkerPath?: string;
  loaderPath?: string;
  reactLoaderPath?: string;
  cssLoaderPath?: string;
  envLoaderPath?: string;
  pageExportName?: Interface["PageExportName"];
  propsExportName?: Interface["PropsExportName"];
  htmlExportName?: Interface["HtmlExportName"];
  rootExportName?: Interface["RootExportName"];
  Html?: UrlOpt;
  Root?: UrlOpt;
  // Direct component overrides (bypasses string resolution)
  components?: {
    Html?: HtmlComponentType<
      Interface["PageProps"],
      Interface["As"],
      Interface["InlineCSS"],
      Interface["ReactType"]
    >;
    Root?: RootComponentType<
      Interface["PageProps"],
      Interface["As"],
      Interface["InlineCSS"],
      Interface["ReactType"]
    >;
    Page?: PageComponentType<Interface["PageProps"], Interface["ReactType"]>;
  };
  build?: BuildConfig;
  dev?: DevConfig;
  css?: RootOptions<Interface["InlineCSS"]>;
  // moduleBaseExceptions?: string[];
  pipeableStreamOptions?: any; // Legacy - kept for backward compatibility
  serverPipeableStreamOptions?: any; // For dev server and RSC worker
  clientPipeableStreamOptions?: any; // For HTML worker
  onMetrics?: OnMetrics;
  onEvent?: OnEvent<Interface>;
  normalizer?: InputNormalizer;
  moduleID?: (
    id: string,
    sourceContent?: string,
    isClientByDirective?: boolean
  ) => string;
  verbose?: boolean;
  rscTimeout?: number; // Timeout in milliseconds for RSC operations
  htmlTimeout?: number; // Timeout in milliseconds for HTML generation operations
  htmlWorkerStartupTimeout?: number; // Timeout in milliseconds for HTML worker startup
  rscWorkerStartupTimeout?: number; // Timeout in milliseconds for RSC worker startup
  fileWriteTimeout?: number; // Timeout in milliseconds for file write operations
  workerShutdownTimeout?: number; // Timeout in milliseconds for worker shutdown operations
  panicThreshold?: PanicThreshold;
}

export type MultiPageHandlerOptions<
  Opt extends ResolvedUserOptions = ResolvedUserOptions
> = Omit<
  CreateHandlerOptions<Opt>,
  | "pagePath"
  | "route"
  | "cssFiles"
  | "propsPath"
  | "rootPath"
  | "htmlPath"
  | "pageProps"
  | "PageComponent"
  | "RootComponent"
  | "HtmlComponent"
>;

export type CreateHandlerOptions<
  Opt extends Record<string, unknown> = ResolvedUserOptions,
  Interface extends ViteReactServerComponentsPlugin = DefaultInterface,
  R = Interface["ReactType"]
> = Pick<
  Opt,
  | "autoDiscover"
  | "css"
  | "pageExportName"
  | "propsExportName"
  | "rootExportName"
  | "htmlExportName"
  | "moduleBase"
  | "moduleRootPath"
  | "moduleBasePath"
  | "moduleBaseURL"
  | "publicOrigin"
  | "onEvent"
  | "onMetrics"
  | "projectRoot"
  | "normalizer"
  | "moduleID"
  | "verbose"
  | "components"
  | "panicThreshold"
  | "projectRoot"
  | "rscTimeout"
  | "htmlTimeout"
  | "fileWriteTimeout"
  | "workerShutdownTimeout"
  | "rscWorkerPath"
  | "htmlWorkerPath"
> & {
  id?: string;
  /** ID of headless stream to reuse for efficiency */
  reuseHeadlessStreamId?: string;
  /** Storage for headless stream reuse Map<id, { PageComponent: any, errored: boolean }> */
  headlessStreamElements?: Map<string, { PageComponent: any; errored: boolean }>;
  signal?: AbortSignal;
  logger: Logger;
  loader: BuildModuleLoader | GenericModuleLoader;
  pagePath: string;
  propsPath?: string;
  rootPath?: string;
  htmlPath?: string;
  pageProps?: Interface["PageProps"];
  PageComponent?:
    | PageComponentType<Interface["PageProps"], R>
    | typeof React.Fragment;
  RootComponent?:
    | RootComponentType<
        Interface["PageProps"],
        Interface["As"],
        Interface["InlineCSS"],
        R
      >
    | typeof React.Fragment;
  HtmlComponent?:
    | HtmlComponentType<
        Interface["PageProps"],
        Interface["As"],
        Interface["InlineCSS"],
        R
      >
    | typeof React.Fragment;
  route: string;
  url?: string;
  as?: Interface["As"];
  manifest: Manifest;
  staticManifest?: Manifest;
  serverManifest?: Manifest;
  clientManifest?: Manifest;
  worker?: Worker; // if available, is preferred worker for inverse streaming
  rscWorker?: Worker; // if rscWorker available, its used for createRscStream
  htmlWorker?: Worker; // if htmlWorker available, its used for createHtmlStream
  server?: ViteDevServer;
  importedCss?: Set<string>;
  cssFiles: Map<string, InterfaceAwareCssContent<Interface>>;
  globalCss: Map<string, InterfaceAwareCssContent<Interface>>;
  serverPipeableStreamOptions?: ServerRenderToPipeableStreamOptions;
  clientPipeableStreamOptions?: ClientRenderToPipeableStreamOptions;
  rscStream?: import("node:stream").Readable; // Optional RSC PassThrough stream to use instead of creating a new one
  htmlStream?: import("node:stream").Readable; // Optional HTML PassThrough stream to use instead of creating a new one
  metrics?: import("./metrics/types.js").StreamMetrics; // Optional metrics to use instead of creating new ones
  build: Pick<
    ResolvedUserOptions["build"],
    | "outDir"
    | "pages"
    | "server"
    | "static"
    | "client"
    | "rscOutputPath"
    | "htmlOutputPath"
    | "assetsDir"
    | "preserveModulesRoot"
  >;
  dev: Pick<ResolvedUserOptions["dev"], "useHtmlWorker" | "useRscWorker">;
  children?: React.ReactNode;
};

export type ResolvePageOptions = {
  pagePath: string;
  pageExportName: string;
  url: string;
};

export type ResolvePropsOptions = {
  propsPath: string;
  propsExportName: string;
  url: string;
};

export type StreamResult =
  | {
      type: "success";
      stream: PassThrough;
      assets?: {
        css?: string[];
      };
    }
  | { type: "error"; error: unknown }
  | { type: "skip" };

export type RouteConfig = {
  path: string;
  // Define page/props paths using patterns
  pattern?: {
    page?: string; // e.g. "page/_theme/[route]/page"
    props?: string; // e.g. "page/_theme/[route]/props"
  };
  // Or use explicit paths
  paths?: {
    page: string; // e.g. "page/home/page"
    props: string; // e.g. "page/home/props"
  };
};

export type BuildOutput = {
  dir?: string;
  rsc?: string;
  ext?: string;
};

export type BuildConfig = {
  useRscWorker?: boolean;
  useHtmlWorker?: boolean;
  pages?: string[] | (() => Promise<string[]> | string[]) | Promise<string[]>;
  assetsDir?: string;
  client?: string; // Output directory for client files
  server?: string; // Output directory for server files
  static?: string; // Output directory for static environment - works in both
  api?: string; // Output directory for API files
  outDir?: string;
  hash?:
    | string
    | {
        format?: "vite" | "hex" | "custom";
        length?: number;
        characters?: string;
        prefix?: string;
        suffix?: string;
      };
  preserveModulesRoot?: boolean;
  rscOutputPath?: string; // defaults: `index.rsc`
  htmlOutputPath?: string; // defaults: `index.html`
  entryFile?: (
    n: PreRenderedChunk,
    ssr: boolean,
    sourceContent?: string
  ) => string;
  chunkFile?: (
    n: PreRenderedChunk,
    ssr: boolean,
    sourceContent?: string
  ) => string;
  assetFile?: (n: PreRenderedAsset, ssr: boolean) => string;
  extensionMap?: Record<string, string>;
  moduleExtension?: string;
  jsExtension?: string;
  cssExtension?: string;
  htmlExtension?: string;
  jsonExtension?: string;
  rscExtension?: string;
  cssModuleExtension?: string;
  nodeExtension?: string;
  /**
   * Controls how pages are rendered during static generation.
   *
   * - `"parallel"` (default): Renders pages in concurrent batches for faster builds.
   *   Use `batchSize` to control concurrency (default: 8).
   * - `"sequential"`: Renders pages one at a time. Slower but uses less memory
   *   and produces deterministic output order.
   */
  renderMode?: "parallel" | "sequential";
  /**
   * Number of pages to render concurrently when `renderMode` is `"parallel"`.
   * Higher values use more memory but build faster.
   * @default 8
   */
  batchSize?: number;
};

export type DevConfig = {
  useHtmlWorker?: boolean | undefined;
  useRscWorker?: boolean | undefined;
};

export type RequestHandler = Connect.NextHandleFunction;

export type RscServerModule = {
  /**
   * Get RSC data for a route
   * @param path - Route path (e.g. "/", "/about")
   * @returns Page component and props
   */
  getRscData: (path: string) => Promise<{
    /** Page component to render */
    Page: React.ComponentType;
    /** Props to pass to the page */
    props: unknown;
  }>;
};

export type RegisterComponentMessage = {
  type: "REGISTER_COMPONENT";
  id: string;
  code: string;
};

export type RscBuildResult = string[];

export type ReactStreamPluginMeta = {
  timing: BuildTiming;
};

export type BuildTiming = {
  start: number;
  configResolved?: number;
  buildStart?: number;
  buildEnd?: number;
  renderStart?: number;
  renderEnd?: number;
  closeBundle?: number;
  render?: number;
  total?: number;
};

export type ResolvedBuildPages = {
  propsMap: Map<string, string>;
  pageMap: Map<string, string>;
  rootMap: Map<string, string>;
  htmlMap: Map<string, string>;
  /**
   * ## routeMap
   *
   * Maps props & page paths to routes
   *
   * @example
   * const routeMap = new Map<string, string[]>();
   * routeMap.set("src/page/home/page.tsx", ["/", "/home"]);
   */
  routeMap: Map<string, string[]>;
  /**
   * ## urlMap
   *
   * Maps urls to props & page paths
   *
   * @example
   * ```ts
   * const urlMap = new Map<string, { props?: string; page: string }>();
   * urlMap.set("/", { props: "/props", page: "/page" });
   * ```
   */
  urlMap: Map<
    string,
    { props?: string; page: string; root?: string; html?: string }
  >;
  errors: unknown[];
};

// Add branded types for safety
export type ModuleId = string & { readonly __brand: unique symbol };
export type PagePath = string & { readonly __brand: unique symbol };

export interface DeserializedRegExp {
  source: string;
  flags: string;
  __isRegExp: boolean;
}

export type RegExpOpt = RegExp | string | DeserializedRegExp;
export type UrlOpt =
  | string
  | ((url: string) => string)
  | ((url: string) => Promise<string>);
export type PageName = "Page";
export type PropsName = "props";
export type HtmlName = "Html";
export type RootName = "Root";

export type HtmlProps<
  PageProps extends ViteReactServerComponentsPlugin["PageProps"] = DefaultInterface["PageProps"],
  InlineCSS extends ViteReactServerComponentsPlugin["InlineCSS"] = DefaultInterface["InlineCSS"],
  As extends ViteReactServerComponentsPlugin["As"] = DefaultInterface["As"],
  R = DefaultInterface["ReactType"]
> = {
  pageProps?: PageProps;
  Page: PageComponentType<PageProps, R>;
  route: string;
  url: string;
  projectRoot: string;
  moduleBase: string;
  moduleBaseURL: string;
  moduleBasePath: string;
  moduleRootPath: string;
  cssFiles: Map<string, CssContent<InlineCSS>>;
  manifest: Manifest;
  Root: RootComponentType<PageProps, As, InlineCSS, R> | typeof React.Fragment;
  globalCss: Map<string, CssContent<InlineCSS>>;
  as?: As;
};

export type PageAsset = {
  type: "css" | "js";
  path: string;
  parentUrl: string;
};

type BaseCssProps = {
  as: string;
  id: string;
};

export type LinkCssProps = BaseCssProps & {
  as: "link";
  type?: never;
  children?: never;
  id: string;
  href: string;
  rel: "stylesheet";
  precedence?: string;
};

export type StyleCssProps = BaseCssProps & {
  as: "style";
  type: "text/css";
  children?: React.ReactNode;
  precedence?: never;
  rel?: never;
  href?: never;
};

export type CssProps<InlineCSS extends InlineCssOpt = InlineCssOpt> = {
  cssFiles: Map<string, CssContent<InlineCSS>>;
};

export type HtmlRenderState = {
  id: string;
  rscStream: PassThrough;
  htmlStream: PassThrough;
  progressStream: PassThrough;
  errorTransform: Transform;
  htmlChunks: string[];
  pipeableStreamOptions: any;
  streamState: StreamMetrics;
};

// Metadata type for tracking render progress

// Simplified result type for the entire render process
export type RenderPagesResult = {
  type: "error" | "success" | "skip";
  error?: unknown;
  route?: string;
  completedRoutes: Set<string>;
  failedRoutes: Map<string, unknown>;
  results: Map<string, RenderPageResult>;
};

export type HandlerAssets<InlineCSS extends InlineCssOpt = InlineCssOpt> = {
  css: CssContent<InlineCSS>[];
  js: string[];
  bootstrapModules: string[];
};

export type CreateHandlerResult<InlineCSS extends InlineCssOpt = InlineCssOpt> =

    | {
        type: "success";
        controller: AbortController;
        stream: PassThrough;
        assets: {
          css: CssContent<InlineCSS>[];
          js: string[];
          bootstrapModules: string[];
        };
        route: string;
        metrics: StreamMetrics;
      }
    | { type: "error"; error: unknown }
    | { type: "skip" };

// Define LoaderContext interface locally
export type LoaderContext = {
  format?: string;
  importAttributes?: Record<string, string>;
  conditions?: string[];
  env?: {
    targetEnvironment?: "client" | "server" | "browser";
  };
  url: string;
  userOptions?: SerializedUserOptions; // Add userOptions to the context
};
// Add type declaration for import.meta.cssModules
declare global {
  interface ImportMeta {
    cssModules?: Record<string, Record<string, string>>;
  }
}

export type VendorInteropConfig = {
  react: string; // e.g. "react"
  reactDOMServer: string; // e.g. "react-dom/server"
};

// Client Browser exports:
// - createFromFetch
// - createFromReadableStream
// - createServerReference
// - createTemporaryReferenceSet
// - encodeReply
// - registerServerReference
export type RSCClientBrowserInteropConfig = {
  createFromFetch: string;
  createFromReadableStream: string;
  createServerReference: string;
  createTemporaryReferenceSet: string;
  encodeReply: string;
  registerServerReference: string;
};

// Client Node exports:
// - createFromNodeStream
// - createServerReference
// - registerServerReference
export type RSCClientNodeInteropConfig = {
  createFromNodeStream: string;
  createServerReference: string;
  registerServerReference: string;
};

// Server Node exports:
// - createTemporaryReferenceSet
// - decodeAction
// - decodeFormState
// - decodeReply
// - decodeReplyFromBusboy
// - registerClientReference
// - registerServerReference
// - renderToPipeableStream
// - unstable_prerenderToNodeStream
export type RSCServerInteropConfig = {
  createTemporaryReferenceSet: string;
  decodeAction: string;
  decodeFormState: string;
  decodeReply: string;
  decodeReplyFromBusboy: string;
  registerClientReference: string;
  registerServerReference: string;
  renderToPipeableStream: string;
  unstable_prerenderToNodeStream: string;
};

export type RSCInteropConfig = {
  client: {
    browser: {
      production: string; // e.g. "react-server-dom-esm/client.browser"
      development: string; // e.g. "react-server-dom-esm/client.browser"
      test: string; // e.g. "react-server-dom-esm/client.browser"
      exports: RSCClientBrowserInteropConfig;
    };
    node: {
      production: string; // e.g. "react-server-dom-esm/client"
      development: string; // e.g. "react-server-dom-esm/client.node"
      test: string; // e.g. "react-server-dom-esm/client.node"
      exports: RSCClientNodeInteropConfig;
    };
  };
  server: {
    production: string; // e.g. "react-server-dom-esm/server"
    development: string; // e.g. "react-server-dom-esm/server.node"
    test: string; // e.g. "react-server-dom-esm/server.node"
    exports: RSCServerInteropConfig;
  };
};

export type FlightTarget =
  | "default"
  | "webpack"
  | "nextjs"
  | "react-server-dom-esm"
  | "react-server-dom-webpack"
  | "react-server-dom-parcel";

export type FlightConfig = {
  rsc: RSCInteropConfig;
  vendor: VendorInteropConfig;
};

// Import configuration from separate file

export type VitePluginMainFn = <
  Opt extends StreamPluginOptions<any> = StreamPluginOptions<any>
>(
  options: Opt,
  strategy?: Strategy
) => Plugin<Opt>[];

export type VitePluginMainAsyncFn = <
  Opt extends StreamPluginOptions<any> = StreamPluginOptions<any>
>(
  options: Opt
) => Promise<Plugin<Opt>[]>;

export type VitePluginFn = <
  Opt extends StreamPluginOptions = StreamPluginOptions
>(
  options: Opt
) => Plugin;

// New types for component resolution strategies
export type ComponentResolutionStrategy =
  | "serializable-path" // Use a path that can be resolved by the worker
  | "direct-import" // Direct import in the worker context
  | "worker-internal" // Component is available internally in the worker
  | "external-reference"; // Reference to external component system

export type SerializableComponentPath = string & {
  readonly __brand: "SerializableComponentPath";
};

export type ComponentResolutionConfig = {
  strategy: ComponentResolutionStrategy;
  path?: SerializableComponentPath;
  moduleId?: string;
  exportName?: string;
};

// Enhanced environment-specific options
export type ClientEnvironmentOptions = {
  // Client environment cannot accept React components directly
  PageComponent?: never;
  RootComponent?: never;
  HtmlComponent?: never;

  // Client environment can accept component resolution configs
  pageComponentConfig?: ComponentResolutionConfig;
  rootComponentConfig?: ComponentResolutionConfig;
  htmlComponentConfig?: ComponentResolutionConfig;

  // Client environment can accept serializable paths
  pagePath?: string;
  rootPath?: string;
  htmlPath?: string;
};

export type ServerEnvironmentOptions = {
  // Server environment can accept React components directly
  PageComponent?: CreateHandlerOptions["PageComponent"];
  RootComponent?: CreateHandlerOptions["RootComponent"];
  HtmlComponent?: CreateHandlerOptions["HtmlComponent"];

  // Server environment can also accept component resolution configs
  pageComponentConfig?: ComponentResolutionConfig;
  rootComponentConfig?: ComponentResolutionConfig;
  htmlComponentConfig?: ComponentResolutionConfig;

  // Server environment can accept serializable paths
  pagePath?: string;
  rootPath?: string;
  htmlPath?: string;
};

// Enhanced ReactStreamCommonOptions with proper environment separation
export type ReactStreamCommonOptions<
  Env extends "client" | "server" = "client" | "server",
  Handles extends keyof CreateHandlerOptions = never
> = Omit<
  CreateHandlerOptions,
  | Handles
  | "PageComponent"
  | "RootComponent"
  | "HtmlComponent"
  | "pagePath"
  | "rootPath"
  | "htmlPath"
> &
  Partial<Pick<CreateHandlerOptions, Handles>> &
  (Env extends "client" ? ClientEnvironmentOptions : ServerEnvironmentOptions);

// Enhanced handler function types with proper environment constraints
export type ReactStreamHandlerFn<
  Env extends "client" | "server",
  Handles extends keyof CreateHandlerOptions,
  ReturnType
> = (options: ReactStreamCommonOptions<Env, Handles>) => ReturnType;

// Type for RSC worker message that enforces serializable constraints
export type RscWorkerMessage = {
  // Only serializable data can be passed to workers
  pageComponentConfig?: ComponentResolutionConfig;
  rootComponentConfig?: ComponentResolutionConfig;
  htmlComponentConfig?: ComponentResolutionConfig;

  // Serializable paths
  pagePath?: string;
  rootPath?: string;
  htmlPath?: string;

  // Other serializable options
  route: string;
  url: string;
  pageProps?: Record<string, unknown>;
  cssFiles: Array<[string, unknown]>; // Serialized Map
  manifest: Record<string, unknown>;

  // Never allow direct component references
  PageComponent?: never;
  RootComponent?: never;
  HtmlComponent?: never;
};

// Enhanced RscRenderOpt with proper serialization constraints
export type RscRenderOpt = WorkerMessage & {
  type: "INIT";
} & {
  dataPort: MessagePort;
  controlPort: MessagePort;
  options: Omit<
    CreateHandlerOptions<ResolvedUserOptions>,
    // Omit non-serializable fields
    | "onEvent"
    | "onMetrics"
    | "loader"
    | "build"
    | "autoDiscover"
    | "normalizer"
    | "moduleID"
    | "PageComponent"
    | "RootComponent"
    | "HtmlComponent"
    | "url"
    | "logger"
    | "cssFiles" // Replace with serializable version
  > & {
    url?: string;
    // Component resolution configs instead of direct components
    pageComponentConfig?: ComponentResolutionConfig;
    rootComponentConfig?: ComponentResolutionConfig;
    htmlComponentConfig?: ComponentResolutionConfig;

    // Serializable CSS files
    cssFiles: Array<[string, unknown]>;

    build: Omit<
      CreateHandlerOptions<ResolvedUserOptions>["build"],
      "entryFileNames" | "chunkFileNames" | "assetFileNames" | "pages"
    > & { pages: string[] };
  };
};

// Type for plugin component references
export type PluginComponentReference = {
  type: "plugin-component";
  componentName: "Html" | "Root" | "Css";
  modulePath: string;
  exportName: string;
};

// Enhanced component resolution types
export type ResolvedComponent<T = unknown> =
  | {
      type: "success";
      component: T;
      source: "direct" | "resolved" | "plugin" | "worker-internal";
    }
  | {
      type: "error";
      error: Error;
      source: "direct" | "resolved" | "plugin" | "worker-internal";
    };

// Type for worker component loader
export type WorkerComponentLoader = {
  loadComponent: (
    config: ComponentResolutionConfig
  ) => Promise<ResolvedComponent>;
  loadPluginComponent: (
    reference: PluginComponentReference
  ) => Promise<ResolvedComponent>;
  hasInternalComponent: (componentName: string) => boolean;
};

// re-exorts
export type {
  RenderMetrics,
  StreamMetrics,
  WorkerStartupMetrics,
  ModuleResolutionMetrics,
};

// Generic React type that can be inferred from user's React import
export type InferReactType<R = React.ReactNode> = R;

// Simple interface override for custom React types
export type CustomInterface<R = React.ReactNode> = {
  ReactType: R;
  PageProps: any;
  As: any;
  PropsExportName: string;
  PageExportName: string;
  RootExportName: string;
  HtmlExportName: string;
  InlineCSS: undefined | boolean;
};

// Core interface types that can be overridden
declare global {
  interface ViteReactServerComponentsPlugin {
    PageProps: any;
    As: any;
    InlineCSS: undefined | boolean;
    ReactType: InferReactType;
    PropsExportName: string;
    PageExportName: string;
    RootExportName: string;
    HtmlExportName: string;
  }
}
// Default interface implementation
export interface DefaultInterface<
  T extends React.ComponentProps<any> = React.ComponentProps<any>,
  As extends
    | React.JSXElementConstructor<any>
    | keyof React.JSX.IntrinsicElements =
    | React.JSXElementConstructor<any>
    | keyof React.JSX.IntrinsicElements
> extends ViteReactServerComponentsPlugin {
  ReactType: InferReactType;
  PageProps: T;
  As: As;
  PropsExportName: PropsName;
  PageExportName: PageName;
  RootExportName: RootName;
  HtmlExportName: HtmlName;
}

// Legacy type aliases for backward compatibility
export type PagePropOpt = DefaultInterface["PageProps"];
export type AsOpt = DefaultInterface["As"];
export type InlineCssOpt = DefaultInterface["InlineCSS"];

// Configurable type system that uses the interface
export type PageComponentType<
  PageProps extends ViteReactServerComponentsPlugin["PageProps"] = DefaultInterface["PageProps"],
  R = DefaultInterface["ReactType"]
> = (props: PageProps) => R;

export type RootComponentType<
  PageProps extends ViteReactServerComponentsPlugin["PageProps"] = DefaultInterface["PageProps"],
  As extends ViteReactServerComponentsPlugin["As"] = DefaultInterface["As"],
  InlineCSS extends ViteReactServerComponentsPlugin["InlineCSS"] = DefaultInterface["InlineCSS"],
  R = DefaultInterface["ReactType"]
> = (props: RootProps<PageProps, InlineCSS, As, R>) => R;

export type RootProps<
  PageProps extends ViteReactServerComponentsPlugin["PageProps"] = DefaultInterface["PageProps"],
  InlineCSS extends ViteReactServerComponentsPlugin["InlineCSS"] = DefaultInterface["InlineCSS"],
  As extends ViteReactServerComponentsPlugin["As"] = DefaultInterface["As"],
  R = DefaultInterface["ReactType"]
> = {
  as: As;
  cssFiles?: Map<string, CssContent<InlineCSS>>;
  pageProps?: Omit<PageProps, "children">;
  Page: PageComponentType<Omit<PageProps, "children">, R>;
  id?: string;
};

/**
 * Boxed component type for the Html component
 */
export type HtmlComponentType<
  T extends ViteReactServerComponentsPlugin["PageProps"] = DefaultInterface["PageProps"],
  As extends ViteReactServerComponentsPlugin["As"] = DefaultInterface["As"],
  InlineCSS extends ViteReactServerComponentsPlugin["InlineCSS"] = DefaultInterface["InlineCSS"],
  R = DefaultInterface["ReactType"]
> = (props: HtmlProps<T, InlineCSS, As, R>) => R;

// Interface-aware type aliases for better type safety
export type InterfaceAwareCssContent<
  Interface extends ViteReactServerComponentsPlugin
> = CssContent<Interface["InlineCSS"]>;

export type InterfaceAwareRootOptions<
  Interface extends ViteReactServerComponentsPlugin
> = RootOptions<Interface["InlineCSS"]>;

export type InterfaceAwareCssComponentType<
  Interface extends ViteReactServerComponentsPlugin,
  R = Interface["ReactType"]
> = CssComponentType<Interface["InlineCSS"], R>;

export type InterfaceAwareCssProps<
  Interface extends ViteReactServerComponentsPlugin
> = CssProps<Interface["InlineCSS"]>;

export type InterfaceAwareHandlerAssets<
  Interface extends ViteReactServerComponentsPlugin
> = HandlerAssets<Interface["InlineCSS"]>;

export type InterfaceAwareCreateHandlerResult<
  Interface extends ViteReactServerComponentsPlugin
> = CreateHandlerResult<Interface["InlineCSS"]>;

export type VitePluginReactClientFn = <
  Opt extends StreamPluginOptions = StreamPluginOptions
>(
  options: Opt
) => Plugin[];

export type VitePluginReactServerFn = <
  Opt extends StreamPluginOptions = StreamPluginOptions
>(
  options: Opt
) => Plugin[];
