import * as Models from '../models/models';
import * as http from 'http';
import * as path from 'path';
import express, { Application, Request, Response } from 'express';
import { GenerateReport } from '../generate-report/GenerateReport';
import { MongooseHelper } from '../../lib/mongoose-report-manager/mongoose-helper';
import { ParamsDictionary } from 'express-serve-static-core';
import type QueryString from 'qs';

export default class Server{
  public app: Application;
  public server!: http.Server;
  private userProperties: Models.UserProperties;
  private mongooseHelper: MongooseHelper;

  public constructor ( ) {
    this.userProperties = {
      disableLog: true,
      jsonDir: `${process.cwd() }/test/unit/data/jsons`,
      metadata: [
        { name: 'browser', value: 'chrome 81' }
      ],
      mongoDb:{
        collections: {
          features: 'Features',
          outputs: 'Outputs',
          reports: 'Reports',
          scenarios: 'Scenarios',
          steps: 'Steps'
        },
        dbHost: 'localhost',
        dbName: 'multiple-cucumber-html-reports',
        dbPort: 27017,
      },
      navigateToFeatureIfThereIsOnlyOne: false,
      openReportInBrowser: true,
      server: {
        serverPort: 3000,
        serverView: 'index'
      }
    };
    this.app = express();
    this.mongooseHelper = new MongooseHelper( this.userProperties );
    this.app.set( 'port', this.userProperties.server?.serverPort );

    this.app.set( 'views', path.join( __dirname, 'views' ) );
    this.app.set( 'view engine', 'ejs' );
    this.app.use( express.urlencoded( { extended: true } ) );
    this.app.use( express.json() );
    this.app.get( '/', async ( req, res: Response ): Promise<void> => {
      const allCollectionData = await this.mongooseHelper.getAllTheElementsOrderedAndFiltered( '',-1,'' );
      res.render( 'index', { collectionData: allCollectionData } );
    } );

    this.app.get( '/mongo/get/datatable', async ( req: Request<ParamsDictionary, unknown, unknown, QueryString.ParsedQs>, res: Response ) => {
      const orderColumnNumber = req.query.order as QueryString.ParsedQs[];
      ( orderColumnNumber[0] ).column as string;
      const columnArray = req.query.columns as QueryString.ParsedQs ;
      const orderColumnName = ( columnArray[( orderColumnNumber[0] ).column as string ] as QueryString.ParsedQs ).data;
      const orderColumnDirection = orderColumnNumber[0].dir === 'asc' ? 1 : -1;
      const searchValue = ( req.query.search as QueryString.ParsedQs ).value as string;
      const allCollectionData = await this.mongooseHelper.getAllTheElementsOrderedAndFiltered( orderColumnName as string, orderColumnDirection, searchValue );
      const returnData = { data: allCollectionData, recordsFiltered: allCollectionData.length, recordsTotal: allCollectionData.length };
      res.send( returnData );
    } );

    this.app.get( '/generateReport', async ( req, res ) => {
      const reportId = req.query.id;
      const jsonReport = await this.mongooseHelper.getReportById( reportId as string );
      await new GenerateReport( ).generateHtmlReport( this.userProperties, jsonReport );
      res.setHeader( 'Content-Type', 'application/json' );
      res.json( { htmlreport: jsonReport } );
    } );
  }

  public startServer(): void{
    this.server = this.app.listen( this.app.get( 'port' ) );
  }

  public closeServer(): void{
    this.server.close();
  }
}
