import { Value as ValuePb } from '@bufbuild/protobuf';

import { GraphQLIntegrationPlugin } from '../plugins/templates/graphqlintegration.js';
import { GOOGLE_SHEETS_PLUGIN_ID } from '../plugins/templates/gsheets.js';
import { MariaDBPlugin } from '../plugins/templates/mariadb.js';
import { MySQLPlugin } from '../plugins/templates/mysql.js';
import { OpenAiPlugin } from '../plugins/templates/openai.js';
import { extendsRestApiIntegrationPlugin } from '../types/plugin/integration.js';

export const transcribeAudioToTextTranslateToEnglishTruthyValues = ['checked', 'true', true];
export const transcribeAudioToTextTranslateToEnglishFalsyValues = [null, undefined, 'false', false];

export const sanitizeV2RequestBody = (apiBody: Record<string, unknown>): Record<string, unknown> => {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  const traverseJSON = (obj: any) => {
    for (const key in obj) {
      if (key === 'step') {
        if (obj.step[OpenAiPlugin.id]) {
          const value = obj.step[OpenAiPlugin.id].transcribeAudioToTextTranslateToEnglish;
          obj.step[OpenAiPlugin.id].transcribeAudioToTextTranslateToEnglish =
            transcribeAudioToTextTranslateToEnglishTruthyValues.includes(value);
          // cast generateTextNewTextMaxTokens as string
          if (obj.step[OpenAiPlugin.id].generateTextNewTextMaxTokens) {
            obj.step[OpenAiPlugin.id].generateTextNewTextMaxTokens = obj.step[OpenAiPlugin.id].generateTextNewTextMaxTokens.toString();
          }
        } else if (obj.step[MariaDBPlugin.id] && 'newValues' in obj.step[MariaDBPlugin.id]) {
          // check if it's an array
          if (Array.isArray(obj.step[MariaDBPlugin.id].newValues)) {
            obj.step[MariaDBPlugin.id].newValues = '';
          }
        } else if (obj.step[MySQLPlugin.id] && 'newValues' in obj.step[MySQLPlugin.id]) {
          // check if it's an array
          if (Array.isArray(obj.step[MySQLPlugin.id].newValues)) {
            obj.step[MySQLPlugin.id].newValues = '';
          }
        } else if (obj.step[GOOGLE_SHEETS_PLUGIN_ID] && 'rowNumber' in obj.step[GOOGLE_SHEETS_PLUGIN_ID]) {
          obj.step[GOOGLE_SHEETS_PLUGIN_ID].rowNumber = obj.step[GOOGLE_SHEETS_PLUGIN_ID].rowNumber.toString();
        } else if (obj.step[GraphQLIntegrationPlugin.id]) {
          const stepConfig = obj.step[GraphQLIntegrationPlugin.id];
          stepConfig.path = '';
          stepConfig.headers = (stepConfig.headers ?? []).filter((header) => header.editable !== false);
        }
        for (const stepProperty of Object.keys(obj.step)) {
          if (stepProperty === 'integration') continue;
          if (extendsRestApiIntegrationPlugin(stepProperty)) {
            const stepConfig = obj.step[stepProperty];
            stepConfig.urlBase = '';
            stepConfig.headers = (stepConfig.headers ?? []).filter((header) => header.editable !== false);
            stepConfig.params = (stepConfig.params ?? []).filter((param) => param.editable !== false);
          }
        }
      } else if (obj?.trigger?.workflow?.parameters?.query) {
        const queryParams = obj.trigger.workflow.parameters.query;
        // iterate over the keys of the query params
        for (const queryParamKey in queryParams) {
          // check if the query param is a string
          if (typeof queryParams[queryParamKey] === 'string') {
            queryParams[queryParamKey] = { values: [queryParams[queryParamKey]] };
          }
        }
      } else if (obj[key] === null) {
        obj[key] = ValuePb.fromJson(null);
      } else if (key === 'variables' && 'items' in obj[key]) {
        const variables = getVariables(obj[key]['items']);
        obj[key]['items'] = variables;
      } else if (typeof obj[key] === 'object') {
        sanitizeV2RequestBody(obj[key]);
      }
    }
  };
  traverseJSON(apiBody);
  return apiBody;
};

type Variable = {
  mode: string;
  value: string;
  type: string;
};

type VariableWithKey = {
  key: string;
} & Variable;

function getVariables(items: Record<string, Variable>): VariableWithKey[] {
  const variables: VariableWithKey[] = [];
  for (const key in items) {
    const variableWithKey = {
      key,
      ...sanitizeVariableValue(items[key])
    };
    variables.push(variableWithKey);
  }
  return variables;
}
function sanitizeVariableValue(variable: Variable): Variable {
  if (Array.isArray(variable.value)) {
    variable.value = `{{${variable.value.join(',')}}}`;
  }
  return variable;
}
