import { Transform } from "node:stream";

/**
 * Regex matching `<script` opening tags.
 * Captures everything between `<script` and `>` to check for existing nonce.
 */
const SCRIPT_OPEN_RE = /<script(\s[^>]*)?\s*>/gi;

/**
 * Wraps an SSR HTML stream to inject `nonce="..."` on every `<script>` tag
 * that doesn't already have a nonce attribute.
 *
 * Workaround for React issue #24883: renderToPipeableStream({ nonce }) only
 * applies the nonce to inline bootstrapScriptContent, not to external
 * bootstrapScripts src URLs.
 */
export function wrapSsrStreamWithNonce(
  stream: NodeJS.ReadableStream,
  nonce: string,
): NodeJS.ReadableStream {
  let buffer = "";

  const transform = new Transform({
    decodeStrings: false,

    transform(chunk: Buffer | string, _encoding, callback) {
      buffer += typeof chunk === "string" ? chunk : chunk.toString("utf-8");

      // Keep a trailing partial `<script...` that might be split across chunks.
      // Find the last `<scr` that might be an incomplete tag.
      const lastOpenBracket = buffer.lastIndexOf("<scr");
      if (lastOpenBracket !== -1 && !buffer.includes(">", lastOpenBracket)) {
        // Incomplete tag — hold the partial in the buffer
        const ready = buffer.slice(0, lastOpenBracket);
        buffer = buffer.slice(lastOpenBracket);
        this.push(injectNonce(ready, nonce));
      } else {
        // No incomplete tag — flush everything
        this.push(injectNonce(buffer, nonce));
        buffer = "";
      }

      callback();
    },

    flush(callback) {
      if (buffer.length > 0) {
        this.push(injectNonce(buffer, nonce));
        buffer = "";
      }
      callback();
    },
  });

  stream.pipe(transform);
  return transform;
}

function injectNonce(html: string, nonce: string): string {
  return html.replace(SCRIPT_OPEN_RE, (match, attrs: string | undefined) => {
    const attrStr = attrs ?? "";
    // Don't inject if nonce already present
    if (/\bnonce\s*=/i.test(attrStr)) {
      return match;
    }
    return `<script nonce="${nonce}"${attrStr}>`;
  });
}
