/* eslint-disable prefer-const */
/* eslint-disable prettier/prettier */
import { All, Controller, Get, Post, Req, Res } from '@nestjs/common';
import axios from 'axios';
import { Response } from 'express';
import { RenderPageOptions } from 'graphql-playground-html';
import { Tab, renderPlaygroundPage } from 'graphql-playground-html/dist/render-playground-page';
import { DefaultQueryData, FisCreateMessageUtility, Query, ServiceProviderData, Uuid } from '../CommonMicroserviceModule/message/FISAppMessageJSUtility/interface/export'
import { HttpService } from "@nestjs/axios";
import { AxiosRequestConfig } from 'axios';
import { GraphQLProviderManager } from '../CommonMicroserviceModule/provider/Fis/interface/export';
import { QueryClientController } from 'src/QueryClientProxy/queryClient.controller';
import * as https from "https";

const fs = require('fs');

const httpsAgent = new https.Agent({
    key: fs.readFileSync(`src/SSL/cert/client-key.pem`),
    cert: fs.readFileSync(`src/SSL/cert/client-crt.pem`),
    ca: [
        fs.readFileSync(`src/SSL/cert/server-ca-crt.pem`)
    ],
});
const axiosHttpsConfig: AxiosRequestConfig = {
    httpsAgent
}

const axiosConfig: AxiosRequestConfig = {
    responseType: "text",
    transformResponse: (res) => {
        // Do your own parsing here if needed ie JSON.parse(res); 
        return res;
    }
}

const axiosHTMLConfig: AxiosRequestConfig = {
    responseType: "text",
    headers: {
        'Accept': "text/html"
    },
    transformResponse: (res) => {
        // Do your own parsing here if needed ie JSON.parse(res); 
        return res;
    }
}
let provider1 = new GraphQLProviderManager();
@Controller()
export class FisAppGraphQlapiController {


    header: {};
    query: string;
    static thisDefaultQueryDatas: DefaultQueryData;
    gqQueryString: string;

    public MessageService: FisCreateMessageUtility = new FisCreateMessageUtility("FisAppID/Name");

    constructor(private readonly http: HttpService) {
        this.checkServerStarted();
    }


    checkServerStarted() {
        let timer;




        console.log(process.env.GRAPHQL_HOST)


        const checkgqConnection = () => {

            this.http.post(process.env.GRAPHQL_HOST + "/graphql", {
                query: defaultQuery(),
            }, axiosHttpsConfig).subscribe({
                next: (v) => {
                    FisAppGraphQlapiController.thisDefaultQueryDatas = v.data.data.defaultQuery;
                    console.log("Graphql server connected")
                    clearInterval(timer)
                },
                error: (e) => {
                    clearInterval(timer)
                    console.count("Waiting for graphql server to be started. " + e)
                    timer = setInterval(checkgqConnection, parseInt(process.env.FAILED_TIMEOUT))
                },
                complete: () => {
                    clearInterval(timer)
                }
            })
        }
        timer = checkgqConnection()

    }

    @All('graphqlapi')
    async graphqlapiform(@Res() res: Response, @Req() req: any) {
        let jadeargument: any = [];

        //check whether the defaultQuery not exist, then get FisAppGraphQlapiController.thisDefaultQueryDatas first array
        let defaultQueryValue = req.body.defaultQuery ? req.body.defaultQuery : FisAppGraphQlapiController.thisDefaultQueryDatas.data[0].queryName;

        //once options selected, set the gqQueryString to selected options value
        FisAppGraphQlapiController.thisDefaultQueryDatas?.data.forEach(res => {
            if (res.queryName == defaultQueryValue) {
                this.gqQueryString = res.queryString;
            }
        })

        if (req.body.Submit == "Click Here to Test FisApp Query >") {
            jadeargument = req.body
            jadeargument['graphql_url'] = './graphQLplayground';
            jadeargument['action'] = './graphqlapi';
            jadeargument['header'] = req.body.header;
            jadeargument['payload'] = req.body.payload;
            jadeargument['defaultQuery'] = FisAppGraphQlapiController.thisDefaultQueryDatas.data
            jadeargument['defaultQueryValue'] = defaultQueryValue

            if (!this.MessageService) {
                this.MessageService = new FisCreateMessageUtility('getQueryMessage');
            }

            const data: {} = {
                header: req.body.header.replace(/\n|\r/g, ""),
                payload: req.body.payload.replace(/\n|\r/g, "").trim()
            }
            await axios.post(process.env.LOCALHOST + '/api/default', this.MessageService.getQueryMessage("ABC", Query.GetData, data)).then(result => {

                if (typeof result.data === 'object') {
                    jadeargument['response'] = JSON.stringify(result.data, null, '  ');
                } else {
                    jadeargument['response'] = result.data;
                }

                res_render('GraphQLAPI', res, jadeargument)
            }).catch(e => {
                jadeargument['message'] = JSON.stringify(e.message, null, '  ');

                res_render('GraphQLAPI', res, jadeargument)
            })

        } else {

            jadeargument = req.body
            jadeargument['graphql_url'] = './graphQLplayground';
            jadeargument['action'] = './graphqlapi';
            jadeargument['defaultQueryAction'] = './graphqlapi';

            jadeargument['generateQuery'] = '/generateQuery';
            jadeargument['defaultQuery'] = FisAppGraphQlapiController.thisDefaultQueryDatas.data
            jadeargument['defaultQueryValue'] = defaultQueryValue

            jadeargument['header'] = defaultHeader();
            jadeargument['payload'] = this.gqQueryString ? this.gqQueryString : defaultPayload().trim();
            res_render('GraphQLAPI', res, jadeargument)
        }



    }

    @Get('graphql')
    retrieveGraphql_get(@Req() req, @Res() res: Response) {
        let sub = new HttpService().get(process.env.GRAPHQL_HOST + "/graphql/", axiosHTMLConfig).subscribe(
            x => {
                let newResponse = {};
                newResponse['headers'] = x['headers'];
                newResponse['data'] = x['data'];

                res.header = newResponse['headers'];
                res.write(newResponse['data']);
                return res.status(200).send();
            },
            err => {
                console.log(err); return err;
            },
            () => {
                console.log("Complete.");
                sub.unsubscribe();
            }
        );
        return sub;
    }

    @Post('graphql')
    retrieveGraphql_post(@Req() req, @Res() res: Response) {
        let sub = new HttpService().post(process.env.GRAPHQL_HOST + "/graphql/", req.body, axiosConfig).subscribe(
            x => {
                let newResponse = {};
                newResponse['headers'] = x['headers'];
                newResponse['data'] = x['data'];

                res.header = newResponse['headers'];
                res.write(newResponse['data']);
                return res.status(200).send();
            },
            err => {
                console.log(err); return err;
            },
            () => {
                console.log("Complete.");
                sub.unsubscribe();
            }
        );
        return sub;
    }

    @Post('multisitereport')
    async postMultisitereport(@Res() res: Response, @Req() req: any) {
        if (!this.MessageService) {
            this.MessageService = new FisCreateMessageUtility('getQueryMessage');
        }
        let defaultQueryValue = req.body.defaultQuery ? req.body.defaultQuery : FisAppGraphQlapiController.thisDefaultQueryDatas.data[0].queryName;
        // let defaultQueryValue = FisAppGraphQlapiController.thisDefaultQueryDatas.data[0].queryName;
        FisAppGraphQlapiController.thisDefaultQueryDatas?.data.forEach(res => {
            if (res.queryName == defaultQueryValue) {
                this.gqQueryString = res.queryString;
            }
        })
        const data: {} = {
            payload: this.gqQueryString.replace(/\n|\r/g, "").trim()
        }

        let jadeargument = req.body;
        jadeargument['url'] = process.env.LOCALHOST + '/api/defaultObservable';
        jadeargument['data'] = JSON.stringify(this.MessageService.getQueryMessage("ABC", Query.GetData, data));
        jadeargument['defaultQueryValue'] = defaultQueryValue;
        jadeargument['action'] = './multisitereport';
        jadeargument['defaultQuery'] = FisAppGraphQlapiController.thisDefaultQueryDatas.data

        let currentProviderName = "QueryModule - " + process.env.SERVERNAME;

        let checkServiceProvider = QueryClientController.provider1.getActiveProviders().find((provider: ServiceProviderData) => { //get the actual provider lists
            if (provider.name == currentProviderName) {
                return provider;
            }
        })

        if (!checkServiceProvider) {
            return "No service provider found";
        } else if (checkServiceProvider.url > "") { // is valid url 
            jadeargument['currentProviderName'] = currentProviderName;
            res_render('MultiSiteReport', res, jadeargument)
        }
    }

    @Get('multisitereport')
    async multisitereport(@Res() res: Response, @Req() req: any) {
        if (!this.MessageService) {
            this.MessageService = new FisCreateMessageUtility('getQueryMessage');
        }
        let defaultQueryValue = FisAppGraphQlapiController.thisDefaultQueryDatas.data[0].queryName;
        FisAppGraphQlapiController.thisDefaultQueryDatas?.data.forEach(res => {
            if (res.queryName == defaultQueryValue) {
                this.gqQueryString = res.queryString;
            }
        })
        const data: {} = {
            payload: this.gqQueryString.replace(/\n|\r/g, "").trim()
        }

        let jadeargument = req.body;
        jadeargument['url'] = process.env.LOCALHOST + '/api/defaultObservable';
        jadeargument['data'] = JSON.stringify(this.MessageService.getQueryMessage("ABC", Query.GetData, data));
        jadeargument['defaultQueryValue'] = defaultQueryValue;
        jadeargument['action'] = './multisitereport';
        jadeargument['defaultQuery'] = FisAppGraphQlapiController.thisDefaultQueryDatas.data

        let currentProviderName = "QueryModule - " + process.env.SERVERNAME;

        let checkServiceProvider = QueryClientController.provider1.getActiveProviders().find((provider: ServiceProviderData) => { //get the actual provider lists
            if (provider.name == currentProviderName) {
                return provider;
            }
        })

        if (!checkServiceProvider) {
            return "No service provider found";
        } else if (checkServiceProvider.url > "") { // is valid url 
            jadeargument['currentProviderName'] = currentProviderName;
            res_render('MultiSiteReport', res, jadeargument)
        }

    }


    @Get('graphQLplayground')
    graphql(@Res() res: Response) {
        res.setHeader('Content-type', 'text/html');
        const options: RenderPageOptions = {
            
        };
        const thisEndpoint = process.env.PLAYGROUND_PATH + "/graphql";

        options.config
        options.settings = {};
        options.endpoint = thisEndpoint;

        const newTab: Tab =
        {
            name: "GraphQL",
            headers: this.header,
            endpoint: thisEndpoint,
            query: this.gqQueryString,
            responses: [""]
        }

        options.tabs = [newTab];

        const playground = renderPlaygroundPage(options)

        res.write(playground)
        res.end();
    }
}




function res_render(renderer: string, res: any, jadeargument: any) {

    res.set('Content-Type', 'text/html') // 2019-10-31
    res.render(renderer, {
        jadeargument: jadeargument
    })
}
function defaultPayload() {
    return `query demo{
        APAccountProfileQuery{
          SummaryResponse{
            __typename
            returnFormatType
          }
          StatusResponse{
            __typename
            status
          }
          APAccountProfileMessage{
            __typename
            data{
              acct_id
              acct_no
            }
          }
        }
      }`;
}

function defaultQuery() {
    return `
    query q1{
        defaultQuery{
            data{
                queryName,
                queryString
            }
        }
    }
    `;
}

function defaultHeader() {
    return JSON.stringify({
        "header": {
            "messageType": "Query",
            "messageID": "942ecfe2-8734-4cff-998e-6a2a5a39c464",
            "messageName": "Query",
            "dateCreated": "2022-03-11T02:19:50.923Z",
            "isAggregate": false,
            "messageProducerInformation": {
                "origin": {
                    "userApplication": {
                        "userAppId": "getQueryMessage",
                        "userAppName": "Client"
                    }
                },
                "components": "Presentation"
            },
            "security": {
                "ucpId": "ABC"
            },
            "messageDataLocation": {
                "isEmbaded": true
            },
            "messageDataFormat": {
                "schemaType": "GraphQL",
                "dataFormat": "Json"
            },
            "requestExecutionMode": 0,
            "resquestTimeOut": 0,
            "query": "General"
        }
    }, null, '  ');


}
function generateId(): string {
    let messageId = new Uuid();
    return messageId.generateId().toString();
}
