import './env.server';
<% if (hydrate) {-%>
import { getAppConfig, renderToHTML as renderAppToHTML, renderToResponse as renderAppToResponse } from '@ice/runtime/server';
<% } else { -%>
import { getAppConfig, getDocumentResponse as renderAppToHTML, renderDocumentToResponse as renderAppToResponse } from '@ice/runtime/server';
<% }-%>
<%- entryServer.imports %>
<% if (hydrate) {-%>
import { commons, statics } from './runtime-modules';
<% }-%>
import * as app from '@/app';
<% if (hasDocument) {-%>
import * as Document from '@/document';
<% } else { -%>
import * as Document from './document';
<% } -%>
import type { RenderMode } from '@ice/runtime';
import type { RenderToPipeableStreamOptions } from 'react-dom/server';
// @ts-ignore
import assetsManifest from 'virtual:assets-manifest.json';
<% if (hydrate) {-%>
import createRoutes from '<%- routesFile %>';
<% } else { -%>
import routesManifest from './route-manifest.json';
<% } -%>
<% if (dataLoaderImport.imports) {-%><%-dataLoaderImport.imports%><% } -%>
<% if (hydrate) {-%><%- runtimeOptions.imports %><% } -%>

<% if (!hydrate) {-%>
// Do not inject runtime modules when render mode is document only.
const commons = [];
const statics = [];
const createRoutes = () => routesManifest;
<% } -%>
const runtimeModules = { commons, statics };

const getRouterBasename = () => {
  const appConfig = getAppConfig(app);
  return appConfig?.router?.basename ?? <%- basename %> ?? '';
}

<% if (hydrate) {-%>
const setRuntimeEnv = (renderMode) => {
  if (renderMode === 'SSG') {
    process.env.ICE_CORE_SSG = 'true';
  } else {
    process.env.ICE_CORE_SSR = 'true';
  }
}
<% } -%>

interface RenderOptions {
  documentOnly?: boolean;
  renderMode?: RenderMode;
  basename?: string;
  serverOnlyBasename?: string;
  routePath?: string;
  disableFallback?: boolean;
  publicPath?: string;
  serverData?: any;
  streamOptions?: RenderToPipeableStreamOptions;
}

export async function renderToHTML(requestContext, options: RenderOptions = {}) {
<% if (hydrate) {-%>
  const { renderMode = 'SSR' } = options;
  setRuntimeEnv(renderMode);
<% }-%>
  const mergedOptions = mergeOptions(options);
  return await renderAppToHTML(requestContext, mergedOptions);
}

export async function renderToResponse(requestContext, options: RenderOptions = {}) {
<% if (hydrate) {-%>
  const { renderMode = 'SSR' } = options;
  setRuntimeEnv(renderMode);
<% }-%>
  const mergedOptions = mergeOptions(options);
  return renderAppToResponse(requestContext, mergedOptions);
}

function mergeOptions(options) {
  const { renderMode = 'SSR', basename, publicPath } = options;

  if (publicPath) {
    assetsManifest.publicPath = publicPath;
  }

  return {
    ...options,
    app,
    assetsManifest,
    createRoutes,
    runtimeModules,
    documentDataLoader: Document.dataLoader,
    Document: Document.default,
    basename: basename || getRouterBasename(),
    renderMode,
    <% if (hydrate) {-%>runtimeOptions: {
<% if (runtimeOptions.exports) { -%>
      <%- runtimeOptions.exports %>
<% } -%>
<% if (locals.customRuntimeOptions) { -%>
      ...<%- JSON.stringify(customRuntimeOptions) %>,
<% } -%>
    },
  <% } -%>};
}
