import Constants from '../../constants.js';
import GrafanaService from '../../services/grafana/grafana-service.js';
import fs from 'fs'
export default class GrafanaPublisher {

  constructor(config) {
    this.fs = fs;
    this.log = null;
    this.grafana = new GrafanaService(config);
    this.config = config;
  }
  async publish(reportFilePath) {
    console.log("Running GrafanaPublisher");
    try {
      let grafanaPublisher = this;
      let logStr = grafanaPublisher.fs.readFileSync(reportFilePath, 'utf8');
      if (!logStr) {
        throw new Error('Could not read logfile');
      }
      grafanaPublisher.log = JSON.parse(logStr);
      if (!grafanaPublisher.log.allResults.meta || !grafanaPublisher.log.allResults.meta.env) {
        throw new Error('Logfile is missing data');
      }

      let testsExecutionResultLog = grafanaPublisher.log.allResults;
      let env = testsExecutionResultLog.meta.env;
      let suite = testsExecutionResultLog.meta.suite;

      let dashboards = this.config.dashboards;
      for (const dashboard of dashboards) {
        let dashboardPanels = await grafanaPublisher.grafana.getPanelsInDashboard(dashboard.dashboardID);
        let panelsToAdd = [];
        let testStepsContent, testStepsCount;
        let testTitle, testTitleSplited;

        if (!this.testCycleTimeSeriesPanelExists(dashboardPanels)) {
          panelsToAdd.push({
            type: Constants.Grafana.TimeSeriesPanelType,
            title: env + " Testcycle graph",
            queryA: "logentrytype:testCycle AND env:" + env + " AND suite:" + suite + " AND reportGroups:" + dashboard.reportGroup + " AND NOT invalid_result:true"
          })
        }

        if (!this.testCycleGaugePanelExists(dashboardPanels)) {
          panelsToAdd.push({
            type: Constants.Grafana.GaugePanelType,
            title: env + " Success Rate",
            queryA: "logentrytype:testCycle AND env:" + env + " AND suite:" + suite + " AND reportGroups:" + dashboard.reportGroup + this.config.kpiLuceneAdditionalFilter,
            queryB: "logentrytype:testCycle AND env:" + env + " AND suite:" + suite + " AND reportGroups:" + dashboard.reportGroup + " AND failurecount:>2" + this.config.kpiLuceneAdditionalFilter
          })
        }

        if (!this.testCycleTablePanelExists(dashboardPanels)) {
          panelsToAdd.push({
            type: Constants.Grafana.TablePanelType,
            title: "MWP " + env + " Testcycle executions",
            queryA: "logentrytype:testCycle AND env:" + env + " AND suite:" + suite + " AND reportGroups:" + dashboard.reportGroup,
          })
        }

        testsExecutionResultLog.describes.forEach(describe => {
          let testUUId = describe.meta.uuid;
          let testReportGroups = Array.from(describe.meta.reportGroups);
          if (dashboard.reportGroup !== 'GENERAL') {
            if (!testReportGroups.includes(dashboard.reportGroup))
              return;
          }
          if (!this.panelExists(dashboardPanels, testUUId, null)) {
            testTitleSplited = describe.title.split('.');
            testTitle = testTitleSplited[testTitleSplited.length - 1];
            testStepsCount = 0;
            testStepsContent = '## ' + testTitle + '\n';
            describe.tests.forEach(testSteps => {
              testStepsCount++;
              testStepsContent += testStepsCount.toString() + '. ' + testSteps.title + '\n'
            })
            panelsToAdd.push({
              type: Constants.Grafana.TextPanelType,
              title: "Scenario " + testTitle,
              content: testStepsContent
            })
            panelsToAdd.push({
              type: Constants.Grafana.TimeSeriesPanelType,
              title: env + " " + testTitle,
              queryA: "env:" + env + " AND uuid:" + testUUId + " AND suite:" + suite
            })
            panelsToAdd.push({
              type: Constants.Grafana.GaugePanelType,
              title: env + " " + testTitle + " Success Rate",
              queryA: "uuid:" + testUUId + " AND env:" + env + " AND suite:" + suite + this.config.kpiLuceneAdditionalFilter,
              queryB: "uuid:" + testUUId + " AND env:" + env + " AND suite:" + suite + " AND failurecount:>0" + this.config.kpiLuceneAdditionalFilter
            })
          }
        });
        if (panelsToAdd.length > 0) {
          await grafanaPublisher.grafana.addPanelsToDashboard(dashboard.dashboardID, panelsToAdd);
        }
      }
    } catch (error) {
      console.error('An error occured in GrafanaPublisher.publish, error:' + error);
      return;
    }
  }

  panelExists(dashboardPanels, panelIdentifier, panelType) {
    if (dashboardPanels !== undefined && dashboardPanels.length > 0) {
      let filteredPanels = dashboardPanels
      .filter(panel => !!panel.targets && panel.targets[0].query.includes(panelIdentifier));
      if(panelType !== null) {
        filteredPanels = filteredPanels.filter(panel => panel.type == panelType);
      }
      return filteredPanels.length > 0;
    }
    return false;
  }

  testCycleTimeSeriesPanelExists(dashboardPanels) {
    return this.panelExists(dashboardPanels, 'logentrytype:testCycle', Constants.Grafana.TimeSeriesPanelType)
  }

  testCycleGaugePanelExists(dashboardPanels) {
    return this.panelExists(dashboardPanels, 'logentrytype:testCycle', Constants.Grafana.GaugePanelType)
  }

  testCycleTablePanelExists(dashboardPanels) {
    return this.panelExists(dashboardPanels, 'logentrytype:testCycle', Constants.Grafana.TablePanelType)
  }

}
