import dotenv = require('dotenv');
dotenv.config({ quiet: true });

import express = require('express');
import cors = require('cors');
import morgan = require('morgan');
import { logger, LogHeader, LogPayload } from './services/logging/logger';

const app = express()

app.use(morgan((tokens: morgan.TokenIndexer, req: express.Request, res: express.Response) => {

  const head: LogHeader = {
    type: 'http',
    level: 'info',
    depth: 'normal',
    timestamp: new Date().toISOString(),
  }

  const payload: LogPayload = {
    message: 'HTTP request completed',
    data: {
      method: tokens.method(req, res),
      path: tokens.url(req, res),
      status: Number(tokens.status(req, res)),
      response_time_ms: Number(tokens['response-time'](req, res)),
      user_id: req.user?.id,
      user_name: req.user?.name,
      user_agent: req.headers['user-agent'],
    },
  }

  logger.log(head.level, head.type, payload.message, payload.data, head.depth)
  return '';
}, {
  skip: (req: express.Request) => {
    return req.originalUrl === '/members/me' || req.originalUrl === '/ping';
  }
}))

app.use(cors({
  origin: [process.env.CLIENT_URL], // your SPA origins
  credentials: true
}));

app.use(express.json())

app.set('trust proxy', 1);

const port = process.env.SERVER_PORT;

//glitchtip setup
import sentry = require('@sentry/node');
if (process.env.DISABLE_GLITCHTIP === "true") {
  logger.info('app', 'Glitchtip disabled', null, 'normal')
} else {
  let dsn = process.env.GLITCHTIP_DSN;
  let release = process.env.APPLICATION_VERSION;
  let environment = process.env.APPLICATION_ENVIRONMENT;
  sentry.init({ dsn: dsn, release: release, environment: environment, integrations: [sentry.captureConsoleIntegration({ levels: ['error'] })] });
  logger.info('app', 'Glitchtip initialized', null, 'normal')
}

//session setup
import path = require('path');
// import session = require('express-session');
import session = require('express-session');
import passport = require('passport');
const SQLiteStore = require('connect-sqlite3')(session);

const cookieOptions: session.CookieOptions = {
  httpOnly: true,
  sameSite: 'lax',
  domain: process.env.CLIENT_DOMAIN,
  maxAge: 1000 * 60 * 60 * 24 * 30, //30 days
}
const sessionOptions: session.SessionOptions = {
  secret: 'whatever',
  resave: false,
  saveUninitialized: false,
  store: new SQLiteStore({ db: 'sessions.db', dir: './' }),
  rolling: true,
  cookie: cookieOptions
}

import { initializeDiscordIntegrations } from './services/integrations/discord';

//event bus setup
initializeDiscordIntegrations();

app.use(session(sessionOptions));
app.use(passport.authenticate('session'));

// Mount route modules
import { applicationRouter } from './routes/applications';
import { memberRanks, ranks } from './routes/ranks';
import { memberRouter } from './routes/members';
import { loaRouter } from './routes/loa';
import { status, memberStatus } from './routes/statuses';
import { authRouter } from './routes/auth';
import { roles, memberRoles } from './routes/roles';
import { courseRouter, eventRouter } from './routes/course';
import { calendarRouter } from './routes/calendar';
import { docsRouter } from './routes/docs';
import { units } from './routes/units';

app.use('/application', applicationRouter);
app.use('/ranks', ranks);
app.use('/memberRanks', memberRanks);
app.use('/members', memberRouter);
app.use('/loa', loaRouter);
app.use('/status', status)
app.use('/memberStatus', memberStatus)
app.use('/roles', roles)
app.use('/memberRoles', memberRoles)
app.use('/course', courseRouter)
app.use('/courseEvent', eventRouter)
app.use('/calendar', calendarRouter)
app.use('/units', units)
app.use('/docs', docsRouter)
app.use('/', authRouter)

app.get('/ping', (req, res) => {
  res.status(200).json({ message: 'pong' });
});

app.listen(port, () => {
  logger.info('app', `Example app listening on port ${port} `)
})
