import type { CreateFromNodeStreamFn } from "./createFromNodeStream.types.js";
import { React, ReactDOMClient } from "../vendor/vendor.client.js";
import { assertNonReactServer } from "../config/getCondition.js";

assertNonReactServer();

/**
 * Client version of createNodeStream.
 *
 * Strategy: Convert RSC stream to React elements using ReactDOMClient.createFromNodeStream.
 * This is the same approach used by the HTML worker for proper CSS handling and RSC processing.
 */
export const createFromNodeStream: CreateFromNodeStreamFn<"client"> =
  function _createFromNodeStreamClient(options) {
    const { rscStream, logger, verbose = false } = options;
    let { moduleRootPath, moduleBasePath, moduleBaseURL } = options;

    if (options.children) {
      if (verbose) {
        logger?.info(
          `[createNodeStream.client] Options already have children, skipping conversion`
        );
      }
      return {
        type: "client" as const,
        children: options.children as React.ReactElement,
      };
    }
    if (!rscStream) {
      throw new Error(
        "[createNodeStream.client] no rscStream nor children provided"
      );
    }

    if (verbose) {
      logger?.info(
        `[createNodeStream.client] Converting RSC stream to React elements, moduleRootPath: ${moduleRootPath}, moduleBasePath: ${moduleBasePath}, moduleBaseURL: ${moduleBaseURL} (type: ${typeof moduleBaseURL})`
      );
    }

    // Ensure moduleBaseURL is a string and not empty
    // React Server DOM needs a valid base URL to resolve modules in the RSC stream
    if (typeof moduleBaseURL !== "string" || !moduleBaseURL) {
      if (verbose && logger) {
        logger.warn(
          `[createNodeStream.client] moduleBaseURL is not a valid string: ${JSON.stringify(
            moduleBaseURL
          )} (type: ${typeof moduleBaseURL}), defaulting to "/"`
        );
      }
      moduleBaseURL = "/";
    }
    if (!moduleRootPath) {
      moduleRootPath = "";
    } else if (!moduleRootPath.endsWith("/")) {
      moduleRootPath = `${moduleRootPath}/`;
    }
    if (!moduleBasePath) {
      moduleBasePath = "";
    } else if (!moduleBasePath.endsWith("/")) {
      moduleBasePath = `${moduleBasePath}/`;
    }

    if (verbose) {
      logger?.info(
        `[createNodeStream.client] Using ReactDOMClient.createFromNodeStream from react-server-dom-esm/client.node`
      );
      logger?.info(
        `[createNodeStream.client] rscStream type: ${typeof rscStream}, readable: ${
          rscStream.readable
        }, destroyed: ${rscStream.destroyed}`
      );
    }

    // Convert RSC stream to React elements using ReactDOMClient.createFromNodeStream
    // This is the same approach used by the HTML worker
    // IMPORTANT: ReactDOMClient.createFromNodeStream returns a Promise that needs to be awaited
    return {
      type: "client" as const,
      children: React.createElement(() => {
        const promise = ReactDOMClient.createFromNodeStream(
          rscStream,
          moduleRootPath,
          moduleBaseURL
        );
        
        return React.use(promise);
      }),
    };
  };
