#!/bin/sh
':' //; exec "$(command -v nodejs || command -v node)" "$0" "$@"

import express, { Request, Response, NextFunction } from 'express';
import path from 'path';
import cors from 'cors';
import http from 'http';
import 'dotenv/config';

import cliRouter from './routers/cli';
import homeRouter from './routers/home';
import pluginsRouter from './routers/plugins';
import webSDKRouter from './routers/webSDK';
import navsRouter from './routers/navigators';
import { createSocketServer } from './websocket';
import { ensureDefaultWorkspace } from './controllers/workspace';
import expressWinston from "express-winston";
import { logger } from './utils/logger';
import {dbInit} from './models';
import database from './database';
import * as Sentry from '@sentry/node';
import { ProfilingIntegration } from '@sentry/profiling-node';
// import cookieParser from 'cookie-parser';
// import {transports} from 'winston';
// import child_process from 'child_process';

// ['spawn', 'exec', 'fork', 'execFile'].forEach(method => {
//   // @ts-ignore
//   const original = child_process[method];
//   // @ts-ignore
//   child_process[method] = function(...args) {
//     logger.info("[LEAK TRACE] child_process.${method} called with:", args[0]);
//     console.trace('[LEAK TRACE] Stack for ${method}');
//     return original.apply(this, args)
//   }
// })
const isPostgresEnabled = process.env.ENABLE_POSTGRES == 'true';
const app = express();

if (process.env.ENABLE_SENTRY) {
  Sentry.init({
    dsn: process.env.SENTRY_DSN,
    integrations: [
      new Sentry.Integrations.Http({ tracing: true }),
      new Sentry.Integrations.Express({ app }),
      new ProfilingIntegration(),
    ],
    tracesSampleRate: 0.1,
    profilesSampleRate: 0.1,
  });

  // IMPORTANT: The requestHandler must be the first middleware on the app
  app.use(Sentry.Handlers.requestHandler());
  app.use(Sentry.Handlers.tracingHandler());
}

// app.use(cookieParser());
app.use(
  expressWinston.logger({
    // transports: [new transports.Console()],
    winstonInstance: logger,
    meta: true,
    msg: "{{req.method}} {{req.url}}",
    expressFormat: true,
    colorize: false,
    ignoreRoute: (req, res) => req.url.endsWith("healthcheck"),
  })
);

app.set('view engine', 'pug');
const server = http.createServer(app);
app.use(cors());
// export const jsonParser = bodyParser.json({limit: '50mb'});
createSocketServer(server);

if (isPostgresEnabled) {
  database.connect();
  dbInit();
  database.sequelize.authenticate().catch((error) => {
    logger.error('Unable to connect to the database:', error);
    if (process.env.ENABLE_SENTRY) {
      Sentry.captureException(error, {
        tags: {
          location: 'database_connect',
          error_type: 'connection_failure'
        }
      });
    }
    throw error;
  });
}

app.use(`/plugin-server/cli`, cliRouter);
app.use(`/plugin-server/home`, homeRouter);
app.use(`/plugin-server/plugins`, pluginsRouter);
app.use(`/plugin-server/navigators`, navsRouter);
app.use(`/plugin-server/webSDK`, webSDKRouter);

// const staticOptions = {
//   maxAge: '1000d', 
//   etag: true,   
//   lastModified: true, 
//   immutable: true 
// };
app.use('/plugin-server/public', express.static(path.resolve(__dirname, 'public')));//, staticOptions));
// For handling spa
app.use('/plugin-server/public/ui/*', (req, res) => {
  res.sendFile(path.resolve(__dirname, 'public/ui/index.html'));
});

app.get('/plugin-server/healthcheck', async (req, res) => {
  try {
    if (isPostgresEnabled) {
      await database.sequelize.authenticate();
    }
    res.send('ok');
  } catch (error) {
    logger.error('Unable to connect to the database:', error);
    res.status(500).send('Database connection failed');
  }
});

if (process.env.ENABLE_SENTRY) {
  app.use(Sentry.Handlers.errorHandler());
}

app.use((err: any, req: Request, res: Response, next: NextFunction) => {
  if (res.headersSent) {
    return next(err)
  }
  res.status(500)
  console.error("GLOBAL_ERROR", err);
  res.end();
});

ensureDefaultWorkspace().then(startupMessage => {
  server.listen(3100, '0.0.0.0', () => {
    logger.log("info",
      `visit http://${process.env.NODE_ENV === "production"
        ? "cli.apptile.io"
        : "localhost:3100"
      }/plugin-server/cli/workspaces/list`
    );
    logger.log("info", startupMessage);
  });
});

