import VaultService from '../core/services/vault-service.js';
import JiraService from '../core/services/jira-service.js';
import AiService from '../core/services/ai-service.js';
import { assert } from 'chai';
import fs from 'fs'

const vaultConfig = {
  vaultConfig: {
    endpoint: 'https://hcp.devops.tech.ec.europa.eu/v1',
    user: process.env.vaultUser,
    password: process.env.vaultPassword,
    namespace: '/EC/DIGIT_B3_CC_VAULT'
  }
}
const secretPath = '/kvccqa/functional/citnet';
const secretKey = 'default';

export default class AIJiraCucumberFlow {
  constructor(context) {
    this.context = context;
  }
  async setVaultService() {
    if (!this.vaultService) {
      console.log('Initializing VaultService...');
      this.vaultService = new VaultService(vaultConfig);

      // Authenticate with vault
      console.log('Authenticating with vault...');
      await this.vaultService.login();
    }

  }
  async setJiraService() {
    await this.setVaultService();
    if (!this.jiraService) {
      // Get Jira credentials from vault
      console.log('Retrieving Jira credentials from vault...');
      const secrets = await this.vaultService.getSecret(secretPath, secretKey);

      if (!secrets || !secrets[secretKey] || !secrets[secretKey].username || !secrets[secretKey].password) {
        throw new Error('Failed to retrieve Jira credentials from vault');
      }

      // Configure Jira service
      console.log('Initializing JiraService...');
      const jiraConfig = {
        baseUrl: 'https://webgate.ec.europa.eu/CITnet/jira',
        username: secrets[secretKey].username,
        password: secrets[secretKey].password,
        projectKey: 'CCQA',
        boardId: '8600'
      };
      this.jiraService = new JiraService(jiraConfig);
    }

  }
  async setAIService() {
    if (!this.aiService) {
      this.aiService = new AiService();
    }
  }
  async generateAiResponse(context) {
    await this.setAIService();
    if(!this.context){
      this.context = context
    }
    let preconditions =
      "Extract a title with tag \"title\" and all possible " +
      " acceptance criteria and associated Gherkin scenarios in a list result will be a json structure like " +
      "{ \"title\": \"title\", \"criteriaList\":[{\"acceptanceCriteria\": \"description of criteria\", \"feature\":[object]}] " +
      "present them only in valid json format as following: " +
      "\"acceptanceCriteria\" tag is \"acceptanceCriteria\", for gherkin tag is \"feature\" properties are \"name\" and \"steps\" " +
      " - steps will be list of strings starting with appropriate gherkin keyword 'Given: ' 'When: ' 'Then: ' " +
      "and the first step will be a login one. Text to process is : "
    await this.aiService.processInfo(preconditions + this.context, "mistral-small-24b-instruct-2501", 30000, true);
    let responseObj = await this.aiService.parseGptJsonResponse();
    this.checkObjElement(responseObj);
    responseObj.context = this.context;
    await fs.writeFileSync( this.aiService.gptResponseFile, JSON.stringify(responseObj));
    return responseObj;
  }
  checkObjElement(objElement) {
    let errors = []
    /* Obj structure:
    object = {
      "title": "",
      "criteriaList": [
        {
          "acceptanceCriteria":	"string of acceptance criteria",
          "feature": {
            "name": "Toggle Button Color",
            "steps" : [array of strings]	
        }
      ]
    }
    */
    //console.log('element to check: ', objElement)
    if (!objElement.title) {
      error.push('title property not present in object\n')
    }
    if (!objElement.criteriaList) {
      error.push('criteriaList property not present in object\n')
      if (!objElement.acceptanceCriteria) {
        error.push('acceptanceCriteria property not present in object\n')
      }
      if (!objElement.feature) {
        error.push('Feature property not present in object\n')
      } else {
        if (!objElement.feature.name) {
          error.push('Feature.name property not present in object\n')
        }
        if (!objElement.feature.steps) {
          error.push('feature.steps property not present in object\n')
        }
      }
    }
    if (errors.length > 0) {
      throw Error('Object element can\'t be used errors: ', errors)
    }
  }
  async addJiraStory(resultObject, issueType = 'Enabler Story') {
    await this.setAIService();
    await this.setJiraService();
    if (!resultObject) {
      resultObject = await this.aiService.parseGptJsonResponse()
    }
    let jiraResponse = await this.createNewJiraIssue(resultObject.title, resultObject.context, issueType);
    let createdIssueKey = jiraResponse.key;
    await this.updateJiraWithData(createdIssueKey, resultObject);
  }
  async createNewJiraIssue(issueSummary, issueDescription, issueType = 'Enabler Story') {
    const createResponse = await this.jiraService.createIssue(
      issueSummary,
      issueDescription,
      issueType  //'New Feature'  // Use New Feature as it seems most reliable
    );
    assert(createResponse != null, 'Create jira issue should not be null');
    console.log(`Successfully created test response: ${createResponse}`);
    let createdIssueKey = createResponse.key;
    console.log(`Successfully created test issue: ${createdIssueKey}`);
    return createResponse;
  }
  // to remove after finish 
  async updateJiraWithData(createdIssueKey,resultObject){
    await this.setJiraService();
    await this.setAIService()
    if (!resultObject) {
      resultObject = await this.aiService.parseGptJsonResponse();
    }
    let acceptanceCriteria = ''
    let cucumberFeatures = ''
    for (let element of resultObject.criteriaList) {
     acceptanceCriteria += element.acceptanceCriteria + '\n'
     cucumberFeatures += '\n'
     cucumberFeatures +=  'Scenario: ' + element.feature.name + '\n';
      for(let feature of element.feature.steps){
        cucumberFeatures += '\t' + feature + '\n';
      }
    }
    let fields = {
      "customfield_18430": cucumberFeatures
    }
    await this.jiraService.updateIssue(createdIssueKey, fields);
    await this.jiraService.updateDescription(createdIssueKey, acceptanceCriteria)
  }
  async deleteJiraIssues(issue) {
    await this.setJiraService();
     await this.jiraService.deleteIssue(issue);

  }

  async createAIResponseAndJiraStory(context){
    await this.setJiraService();
    await this.setAIService();
    let result = await this.generateAiResponse(context);
    await this.addJiraStory(result);
  }
}

let test = new AIJiraCucumberFlow();
//await test.deleteJiraIssues('CCQA-4688')
await test.generateAiResponse('We have a toggle button that will be green when enabled and grey when its not the toggle button will only be available after the task is claimed and when you enable it the user will be able to complete the task.')
//await test.createAIResponseAndJiraStory('The current filter of a section will then only be retained in memory and will be lost upon refresh. It will not be lost by navigating between different sections. Saved or predefined filters and the way they apply or persist are not affected by this change.')
//await test.createAIResponseAndJiraStory('Rework candidates picker in order to make it more intuitive and enable new features: one line string for the names, replacement of me with current use desc, grouping of user logged in entries from other candidates, revamp of supervised by me entry, introduction of a new entry logged in user available when the user can create shared filters (available just in DEV).')
//await test.updateJiraWithData('CCQA-4667')
