import type { EntryContext } from '@remix-run/node';
import { RemixServer } from '@remix-run/react';
import { renderToReadableStream } from 'react-dom/server';

const ABORT_DELAY = 5000;

export async function streamToText(stream: ReadableStream<Uint8Array>): Promise<string> {
  let result = '';
  const reader = stream.pipeThrough(new TextDecoderStream()).getReader();
  while (true) { // eslint-disable-line no-constant-condition
    const { done, value } = await reader.read();
    if (done) {
      break;
    }

    result += value;
  }
  return result;
}

type CachedResponse = {
  html: string;
  date: Date;
}
const cache = new Map<string, CachedResponse>();

export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  remixContext: EntryContext
) {
  // // check if we have a cached response in memory
  // const cachedResponse = cache.get(request.url);
  // if (cachedResponse) {
  //   console.log('Serving from cache', request.url);
  //   // if we have a cached response, check if it's less than 5 seconds old
  //   const now = new Date();
  //   const diff = now.getTime() - cachedResponse.date.getTime();
  //   if (true || diff < 5000) {
  //     // if it's less than 5 seconds old, return the cached response
  //     responseHeaders.set('Content-Type', 'text/html');
  //     return new Response(cachedResponse.html, {
  //       headers: responseHeaders,
  //       status: responseStatusCode,
  //     });
  //   }
  // }

  let didError = false;
  const chunks: Uint8Array[] = [];

  const body = await renderToReadableStream(
    <RemixServer context={remixContext} url={request.url} />,
    {
      onError: (error: unknown) => {
        didError = true;
        console.error(error);
      }
    }
  );

  const [toReponse, toCache] = body.tee();

  streamToText(toCache).then(html => {
    console.log('I have the HTML!', html.length);
  });

  const headers = new Headers(responseHeaders);
  headers.set("Content-Type", "text/html");
  const response = new Response(toReponse, {
    headers,
    status: didError ? 500 : responseStatusCode,
  });
  return response;
}
