const crypto = require("crypto");

// Ключ шифрования из переменных окружения или дефолтный (для разработки)
// В продакшене ОБЯЗАТЕЛЬНО установите ENCRYPTION_KEY в .env файле!
// Ключ должен быть строкой минимум 32 символа для AES-256
const ENCRYPTION_KEY_STRING =
  process.env.ENCRYPTION_KEY || "default-key-change-in-production-min-32-chars";

// Проверка ключа при запуске
const isProduction = process.env.NODE_ENV === "production";
const isUsingDefaultKey = !process.env.ENCRYPTION_KEY;

// В продакшене требуем установленный ключ
if (isProduction && isUsingDefaultKey) {
  console.error(
    "❌ ОШИБКА: ENCRYPTION_KEY не установлен в переменных окружения!"
  );
  console.error(
    "Установите ENCRYPTION_KEY в .env файле перед запуском в продакшене."
  );
  console.error("Пример: ENCRYPTION_KEY=ваш-случайный-ключ-минимум-32-символа");
  process.exit(1);
}

// Предупреждение в разработке
if (!isProduction && isUsingDefaultKey) {
  console.warn("⚠️  ПРЕДУПРЕЖДЕНИЕ: Используется дефолтный ключ шифрования!");
  console.warn("Для безопасности установите ENCRYPTION_KEY в .env файле.");
  console.warn("Пример: ENCRYPTION_KEY=ваш-случайный-ключ-минимум-32-символа");
}

// Преобразуем строку ключа в 32-байтовый ключ для AES-256
const ENCRYPTION_KEY = crypto
  .createHash("sha256")
  .update(ENCRYPTION_KEY_STRING)
  .digest();

// Длина IV (Initialization Vector) для AES-256-GCM
const IV_LENGTH = 16;

// Метка аутентификации для проверки целостности данных
const AUTH_TAG_LENGTH = 16;

/**
 * Шифрует текст заметки
 * @param {string} text - Текст для шифрования
 * @returns {string} - Зашифрованный текст в формате base64:iv:authTag
 */
function encrypt(text) {
  if (!text || text.trim() === "") {
    return text;
  }

  try {
    // Генерируем случайный IV для каждой операции шифрования
    const iv = crypto.randomBytes(IV_LENGTH);

    // Создаем шифр с алгоритмом AES-256-GCM
    const cipher = crypto.createCipheriv("aes-256-gcm", ENCRYPTION_KEY, iv);

    // Шифруем текст
    let encrypted = cipher.update(text, "utf8", "base64");
    encrypted += cipher.final("base64");

    // Получаем метку аутентификации для проверки целостности
    const authTag = cipher.getAuthTag();

    // Возвращаем зашифрованные данные в формате: base64:iv:authTag
    return `${encrypted}:${iv.toString("base64")}:${authTag.toString(
      "base64"
    )}`;
  } catch (error) {
    console.error("Ошибка шифрования:", error);
    throw new Error("Ошибка шифрования данных");
  }
}

/**
 * Дешифрует текст заметки
 * @param {string} encryptedText - Зашифрованный текст в формате base64:iv:authTag
 * @returns {string} - Расшифрованный текст
 */
function decrypt(encryptedText) {
  if (!encryptedText || encryptedText.trim() === "") {
    return encryptedText;
  }

  // Проверяем формат зашифрованных данных
  // Если формат не соответствует ожидаемому, возможно это старая незашифрованная заметка
  const parts = encryptedText.split(":");
  if (parts.length !== 3) {
    // Если это не зашифрованный текст, возвращаем как есть (для обратной совместимости)
    console.warn("Обнаружен незашифрованный текст заметки");
    return encryptedText;
  }

  try {
    const [encrypted, ivBase64, authTagBase64] = parts;

    // Преобразуем IV и метку аутентификации из base64
    const iv = Buffer.from(ivBase64, "base64");
    const authTag = Buffer.from(authTagBase64, "base64");

    // Создаем дешифратор с алгоритмом AES-256-GCM
    const decipher = crypto.createDecipheriv("aes-256-gcm", ENCRYPTION_KEY, iv);

    // Устанавливаем метку аутентификации для проверки целостности
    decipher.setAuthTag(authTag);

    // Дешифруем текст
    let decrypted = decipher.update(encrypted, "base64", "utf8");
    decrypted += decipher.final("utf8");

    return decrypted;
  } catch (error) {
    console.error("Ошибка дешифрования:", error);
    // Если не удалось дешифровать, возможно это старая заметка
    // Возвращаем оригинальный текст
    return encryptedText;
  }
}

/**
 * Проверяет, является ли текст зашифрованным
 * @param {string} text - Текст для проверки
 * @returns {boolean} - true если текст зашифрован
 */
function isEncrypted(text) {
  if (!text || text.trim() === "") {
    return false;
  }
  const parts = text.split(":");
  return parts.length === 3;
}

module.exports = {
  encrypt,
  decrypt,
  isEncrypted,
};
