// Утилита для фильтрации нежелательного контента
const fs = require('fs');
const path = require('path');

// Список русских нецензурных слов и других запрещенных слов
const russianBadWords = [
  'блядь', 'хуй', 'пизда', 'ебать', 'ебал', 'ебло', 'хуесос', 'пидор', 'пидорас',
  'мудак', 'говно', 'залупа', 'хер', 'манда', 'спермоед', 'шлюха', 'соска', 'шалава',
  'дебил', 'дрочить', 'дрочка', 'ебанутый', 'выродок', 'шмара', 'сука', 'членосос',
  'гандон', 'гондон', 'гнида', 'вагина', 'хуи', 'жопа', 'шлюхи', 'проститутка'
];

// Список запрещенных слов и фраз для дейтинг-приложения
const datingAppBadWords = [
  'проститутка', 'интим', 'секс за деньги', 'эскорт', 'интим услуги',
  'заплачу', 'заплати', 'минет', 'массаж с интимом'
];

/**
 * Загружает список запрещенных слов из файла
 * @param {string} filePath - Путь к файлу со списком запрещенных слов
 * @return {Array<string>} - Массив запрещенных слов
 */
function loadBadWordsFromFile(filePath) {
  try {
    if (fs.existsSync(filePath)) {
      const content = fs.readFileSync(filePath, 'utf8');
      const words = content.split('\n')
        .map(word => word.trim())
        .filter(word => word && !word.startsWith('//') && word.length >= 3);
      console.log(`Загружено ${words.length} запрещенных слов из файла ${filePath}`);
      return words;
    }
  } catch (error) {
    console.error(`Ошибка при загрузке слов из файла ${filePath}:`, error.message);
  }
  return [];
}

class ProfanityFilter {
  constructor() {
    // Загружаем слова из файлов
    const russianFileWords = loadBadWordsFromFile(path.join(__dirname, 'words.txt'));
    const englishFileWords = loadBadWordsFromFile(path.join(__dirname, 'en.txt'));
    
    // Объединяем все источники запрещенных слов
    this.badWords = [
      ...russianBadWords,
      ...datingAppBadWords,
      ...russianFileWords,
      ...englishFileWords
    ];

    // Создаем регулярные выражения для проверки производных слов
    this.generateWordPatterns(this.badWords);
    
    console.log(`Всего загружено ${this.badWords.length} запрещенных слов`);
  }

  /**
   * Создает регулярные выражения для проверки производных слов
   * @param {Array<string>} words - Список базовых запрещённых слов
   */
  generateWordPatterns(words) {
    this.wordPatterns = words
      .filter(word => word && word.length >= 3) // Снижаем минимальную длину до 3 символов
      .map(word => {
        // Создаем шаблон с учетом возможных разделителей и замен символов
        const baseWord = word
          .replace(/[еёо]/g, '[еёо]') // Учитываем замену е/ё/о
          .replace(/а/g, '[аa@]')     // Учитываем замену а на a латинскую или @
          .replace(/о/g, '[оo0]')     // Учитываем замену о на o латинскую или 0
          .replace(/е/g, '[еe]')      // Учитываем замену е на e латинскую
          .replace(/с/g, '[сc]')      // Учитываем замену с на c латинскую
          .replace(/р/g, '[рp]')      // Учитываем замену р на p латинскую
          .replace(/х/g, '[хx]')      // Учитываем замену х на x латинскую
          .replace(/у/g, '[уy]')      // Учитываем замену у на y латинскую
          .replace(/и/g, '[иi]');     // Учитываем замену и на i
        
        // Создаем регулярку, которая учитывает:
        // - возможные разделители между буквами (точки, пробелы, дефисы)
        // - возможные окончания слов
        const chars = baseWord.split('');
        const patternWithSeparators = chars.join('[\\s\\._\\-]*');
        
        return new RegExp(`\\b${patternWithSeparators}[а-яёa-z]*\\b`, 'i');
      });
  }

  /**
   * Проверяет, содержит ли текст запрещенные слова или их производные
   * @param {string} text - Текст для проверки
   * @return {boolean} - true, если текст содержит запрещенные слова, иначе false
   */
  hasProfanity(text) {
    if (!text) return false;
    
    // Нормализуем текст, убирая лишние символы и разделители
    const normalizedText = text.toLowerCase()
      .replace(/[\s\._\-]+/g, ''); // Удаляем пробелы, точки, подчеркивания, дефисы
    
    // Проверяем на простое вхождение запрещенных слов
    for (const word of this.badWords) {
      if (normalizedText.includes(word.toLowerCase())) {
        return true;
      }
    }

    // Дополнительная проверка на производные слова через регулярные выражения
    return this.wordPatterns.some(pattern => pattern.test(text.toLowerCase()));
  }

  /**
   * Проверяет, содержит ли объект запрещенные слова в указанных полях
   * @param {Object} obj - Объект для проверки
   * @param {Array<string>} fields - Массив имен полей для проверки
   * @return {Object} - Объект с результатами проверки { isProfane: boolean, field: string|null }
   */
  validateObject(obj, fields) {
    for (const field of fields) {
      if (obj[field] && this.hasProfanity(obj[field])) {
        return { isProfane: true, field };
      }
    }
    return { isProfane: false, field: null };
  }

  /**
   * Заменяет запрещенные слова в тексте на звездочки
   * @param {string} text - Исходный текст
   * @return {string} - Очищенный текст
   */
  clean(text) {
    if (!text) return '';
    
    let cleanedText = text;
    
    // Проверяем и заменяем на звездочки каждое запрещенное слово
    this.badWords.forEach(word => {
      const regex = new RegExp(`\\b${word}\\b`, 'gi');
      cleanedText = cleanedText.replace(regex, match => '*'.repeat(match.length));
    });
    
    // Затем проверяем на производные слова и заменяем их
    this.wordPatterns.forEach(pattern => {
      cleanedText = cleanedText.replace(pattern, match => '*'.repeat(match.length));
    });
    
    return cleanedText;
  }

  /**
   * Добавляет новое запрещенное слово в фильтр
   * @param {string|Array<string>} words - Слово или массив слов для добавления
   */
  addWords(words) {
    // Добавляем слова в список запрещенных слов
    if (Array.isArray(words)) {
      this.badWords.push(...words);
      this.generateWordPatterns(words);
    } else {
      // Если передано одно слово
      this.badWords.push(words);
      this.generateWordPatterns([words]);
    }
  }

  /**
   * Проверяет является ли слово запрещенным
   * @param {string} word - Слово для проверки
   * @return {boolean} - true, если слово запрещено, иначе false
   */
  isProfane(word) {
    return this.hasProfanity(word);
  }
}

// Экспортируем экземпляр фильтра для использования в приложении
const profanityFilter = new ProfanityFilter();

module.exports = profanityFilter;