import express from "express";
import React from "react";
import { Provider } from "react-redux";
import { renderToString } from "react-dom/server";
import { StaticRouter } from "react-router-dom";
import { Helmet } from "react-helmet";
import serialize from "serialize-javascript";
import App from "../common/app";
import { AppState } from "../common/store";
import configureStore from "../common/store/configure";
import path from "path";
import { ChunkExtractor, ChunkExtractorManager } from "@loadable/server";
import { dehydrate, QueryClientProvider } from "@tanstack/react-query";
import { queryClient } from "../common/core";

export const render = (req: express.Request, state: AppState) => {
  const store = configureStore(state);

  const context = {};
  // This is the stats file generated by webpack loadable plugin
  const statsFile = path.resolve("./build/loadable-stats.json");
  // We create an extractor from the statsFile
  const extractor = new ChunkExtractor({ statsFile, entrypoints: ["client"] });
  const dehydratedState = dehydrate(queryClient);

  const markup = renderToString(
    <ChunkExtractorManager extractor={extractor}>
      <Provider store={store}>
        <QueryClientProvider client={queryClient}>
          <StaticRouter location={req.originalUrl} context={context}>
            <App />
          </StaticRouter>
        </QueryClientProvider>
      </Provider>
    </ChunkExtractorManager>
  );

  const finalState = store.getState();

  const helmet = Helmet.renderStatic();
  const headHelmet = helmet.meta.toString() + helmet.title.toString() + helmet.link.toString();
  const scriptTags = extractor.getScriptTags();
  const linkTags = extractor.getLinkTags();
  const styleTags = extractor.getStyleTags();

  queryClient.clear();
  return `<!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="utf-8" />
                <meta name="viewport" content="width=device-width, initial-scale=1" />
                <meta name="theme-color" content="#000000"/>
                <link rel="icon" href="/favicon.png" />
                <link rel="apple-touch-icon" href="/logo192.png" />
                <link rel="manifest" href="/manifest.json" />
                ${headHelmet}
                ${linkTags}
                ${styleTags}
                <style>
                  *::before, *::after {
                    box-sizing: border-box;
                  }
                  
                  .ecency-global-loader {
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    flex-direction: column;
                    height: 100%;
                    width: 100%;
                    z-index: 100;
                    position: fixed;
                    background-color: #fff;
                    top: 0;
                    left: 0;
                    transition: 0.4s;
                  }
                  
                  .dark .ecency-global-loader {
                    background: #161d26;
                  }
                  
                  .ecency-global-loader.ecency-global-loader-hidden {
                    opacity: 0;
                    visibility: hidden;
                    transform: scale(2);
                  }
                  
                  .ecency-global-loader-spinner {
                     position: relative;
                     height: 112px;
                     width: 112px;
                  }
                  
                  .ecency-global-loader-spinner:before,
                  .ecency-global-loader-spinner:after {
                     border-radius: 50%;
                     content: '';
                     position: absolute;
                  }
                  
                  .ecency-global-loader-spinner:before {
                     background: #474bff;
                     height: 22.4px;
                     width: 22.4px;
                     top: 50%;
                     left: 50%;
                     transform: translate(-50%, -50%);
                  }
                  
                  .ecency-global-loader-spinner:after {
                     animation: pulse-t3pv1p 1.5s infinite;
                     border: 11.2px solid #474bff;
                     height: 100%;
                     width: 100%;
                  }
                  
                  @keyframes pulse-t3pv1p {
                     from {
                        opacity: 1;
                        transform: scale(0);
                     }
                  
                     to {
                        opacity: 0;
                        transform: scale(1);
                     }
                  }
                 
                  .ecency-global-loader-title {
                    font-family: -apple-system, Helvetica, "Segoe UI", sans-serif;
                    font-weight: bold;
                    text-transform: uppercase;
                    letter-spacing: 0.5rem;
                    color: #404f66;
                  }
                </style>
            </head>
            <body class="${state.global.theme === "night" ? "dark" : ""}">
                <div id="root">${markup}</div>
                <div class="ecency-global-loader">
                  <div class="ecency-global-loader-spinner"></div>
                  <div class="ecency-global-loader-title">Ecency</div>
                </div>
                <script>
                  window.__PRELOADED_STATE__ = ${serialize(finalState)}
                  window.__REACT_QUERY_STATE__ = ${serialize(dehydratedState)}
                </script>
                ${scriptTags}
                <script type="application/ld+json">
                  {
                    "@context": "https://schema.org",
                    "@type": "WebSite",
                    "url": "https://ecency.com/",
                    "potentialAction": [{
                      "@type": "SearchAction",
                      "target": {
                        "@type": "EntryPoint",
                        "urlTemplate": "https://ecency.com/search/?q={search_term_string}"
                      },
                      "query-input": "required name=search_term_string"
                    }]
                  }
                </script>
                <style>
                  body {
                    display: block !important;
                  }
                </style>
            </body>
        </html>`;
};
