import AdmZip from "adm-zip";
import path from "path";
import { KindEnums } from "@apic/api-model/common/StudioEnums.js";
import { EnvironmentAsset } from "../../model/assets-model.js";
import { equalsIgnoreCase } from "../common/data-helper.js";
import { isYamlFile } from "../common/fs-helper.js";
import { convertParsedYmlToString, parseYamlContent } from "../common/yaml-helper.js";
import {
  FAILED_TO_PROCESS_ENTRY,
  INVALID_ENV_VARIABLE_FORMAT,
  KEY_MISSING,
  NO_ENV_FILE,
  VALUE_MISSING,
} from "../../constants/message-constants.js";
import { EQUAL } from "../../constants/app-constants.js";
import { showError } from "../common/message-helper.js";



const parseEnvInput = (input: string): Record<string, string> => {
  const result: Record<string, string> = {};

  if (!input.trim()) {
    return result;
  }

  const pairs = input.split(/,(?=(?:[^'"]*['"][^'"]*['"])*[^'"]*$)/);

  pairs.forEach((pair) => {
    if (!pair.trim()) {
      return;
    }

    const [key, ...valueParts] = pair.split(EQUAL);

    if (!key || !key.trim()) {
      throw new Error(`${INVALID_ENV_VARIABLE_FORMAT} ${KEY_MISSING}` + pair);
    }

    const value = valueParts.join(EQUAL).trim();
    if (!value) {
      throw new Error(
        `${INVALID_ENV_VARIABLE_FORMAT} ${VALUE_MISSING}` + key.trim()
      );
    }

    const finalKey = key.replace(/^['"]|['"]$/g, "").trim();
    const finalValue = value.replace(/^['"]|['"]$/g, "").trim();
    result[finalKey] = finalValue;
  });

  return result;
};

const updateEnvironmentAssets = (yamlContent: EnvironmentAsset,envMap: Record<string, string>): EnvironmentAsset => {
  if (!equalsIgnoreCase(yamlContent.kind || "", KindEnums.Environment)) {
    return yamlContent;
  }

  if (!yamlContent.spec) {
    yamlContent.spec = { variables: [] };
  }
  const variables = yamlContent.spec.variables || [];
  Object.keys(envMap).forEach((key) => {
    const existingVar = variables.find(
      (v) => v.key && equalsIgnoreCase(v.key, key)
    );
    if (!existingVar) {
      variables.push({ key, value: envMap[key] });
    } else {
      existingVar.value = envMap[key];
    }
  });

  yamlContent.spec.variables = variables;

  return yamlContent;
};

const updateZipBuffer = (entries: AdmZip.IZipEntry[],inputMap: Record<string, string>,zip: AdmZip): void => {
  entries.forEach((entry) => {
    try {
      const content = entry.getData().toString('utf-8');
      const yamlContent = parseYamlContent(content);
      if(!yamlContent){
        return;
      }
      const updatedEnvironmentContent = updateEnvironmentAssets(yamlContent.toJS(), inputMap);
      if (yamlContent.hasIn(['spec', 'variables'])) {
        yamlContent.setIn(['spec', 'variables'], updatedEnvironmentContent.spec.variables);
      }
      
      const updatedContent = convertParsedYmlToString(yamlContent);
      if (content !== updatedContent) {
        zip.updateFile(entry.entryName, Buffer.from(updatedContent, 'utf-8'));
      }
    } catch (error) {
      showError(`${FAILED_TO_PROCESS_ENTRY} ${entry.entryName}: ${(error as Error).message}`);
    }
  });
};

const updateEnvironmentAssetInZip = async (zipBuffer: Buffer,envMap: Record<string, string>,directory: string): Promise<Buffer> => {
  const zip = new AdmZip(zipBuffer);
  const entries = zip.getEntries();

  const yamlEntries = entries.filter((entry) => {
    const entryName = entry.entryName;
    const normalizedPath = path.normalize(entryName);
    return (
      normalizedPath.startsWith(path.normalize(directory)) &&
      isYamlFile(normalizedPath)
    );
  });

  if (yamlEntries.length === 0) {
    throw new Error(`${NO_ENV_FILE} ${directory}`);
  }

  updateZipBuffer(yamlEntries, envMap, zip);

  return zip.toBuffer();
};

export { parseEnvInput, updateEnvironmentAssetInZip };
