import path from 'path';
import type { Request, Response } from 'express';
import express from 'express';
import webpack from 'webpack';
import morgan from 'morgan';
import compress from 'compression';
import webpackDevMiddleware from 'webpack-dev-middleware';
import webpackHotMiddleware from 'webpack-hot-middleware';
import { SERVER_PORT } from '@core/const';

const isDevelopment = process.env.NODE_ENV === 'development';
const staticPath = path.join(process.cwd(), './build/client');

const app = express();
const start = () => {
  app.listen(SERVER_PORT, () => console.log(`The app listening at http://localhost:${SERVER_PORT}`));
};

app.use(
  morgan('dev', {
    skip(req: Request) {
      return /^\/(static|__webpack_hmr)/i.test(req.path);
    }
  })
);

app.use(compress());
app.use('/static', express.static(staticPath));

if (isDevelopment) {
  const webpackConfig = require('./.config/webpack/config') as any[];

  const compiler = webpack(webpackConfig);

  const devMiddleware = webpackDevMiddleware(compiler, {
    publicPath: webpackConfig[0].output.publicPath,
    serverSideRender: true,
    writeToDisk: (pathname: string) => /server/.test(pathname)
  });

  app.use(devMiddleware);
  app.use(webpackHotMiddleware(compiler.compilers[0]));

  devMiddleware.waitUntilValid(start);
}

app.get('/', (req: Request, res: Response) => {
  const userAgent = req.headers['user-agent'] ?? '';

  const pathToRenderer = isDevelopment ? './build/server/renderer.js' : '../server/renderer.js';

  const resolved = require.resolve(pathToRenderer);

  if (isDevelopment && require.cache[resolved]) {
    delete require.cache[resolved];
  }

  const render = require(resolved).default;

  const html = render({
    root: 'main',
    userAgent
  });

  res.status(200).send(html);
});

app.on('error', console.error);

if (!isDevelopment) {
  start();
}
