/**
 * Copyright (c) 2025 SoftCorporation LLC. All rights reserved.
 *
 * The Software License, Version 1.0
 *
 * SoftCorporation LLC. grants you ("Licensee") a non-exclusive, royalty free,
 * license to use, modify and redistribute this software in source and binary
 * code form, provided that the following conditions are met:
 *
 * 1. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        SoftCorporation LLC. (http://www.softcorporation.com)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 2. This software and SoftCorporation name must not be used to
 *    promote products derived from the software without prior
 *    written permission. For written permission, please contact
 *    info@softcorporation.com.
 *
 * This software is provided "AS IS," without a warranty of any kind.
 * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED.
 * IN NO EVENT SHALL THE SOFTCORPORATION BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION).
 *
 */
package com.softcorporation.sandi.base.service;

import static org.junit.jupiter.api.Assertions.*;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.test.util.ReflectionTestUtils;

import com.softcorporation.sandi.base.service.solr.SolrSynonymService;
import com.softcorporation.sandi.base.util.SynonymException;

public class SynonymServiceMultiLanguageTest {

    @TempDir
    Path tempDir;
    
    private SolrSynonymService synonymService;
    
    @BeforeEach
    public void setUp() throws IOException {
        synonymService = new SolrSynonymService();
        
        ReflectionTestUtils.setField(synonymService, "sandiLanguages", "en,fr,de,ru,it,es");
        ReflectionTestUtils.setField(synonymService, "synonymsDirectory", tempDir.toString());
        ReflectionTestUtils.setField(synonymService, "stemmingEnabled", true);
        
        createTestSynonymFiles();
        
        synonymService.init();
    }
    
    private void createTestSynonymFiles() throws IOException {
        createEnglishSynonyms();
        createFrenchSynonyms();
        createGermanSynonyms();
        createRussianSynonyms();
        createItalianSynonyms();
        createSpanishSynonyms();
    }
    
    private void createEnglishSynonyms() throws IOException {
        File synonymFile = tempDir.resolve("english_synonyms.txt").toFile();
        try (FileWriter writer = new FileWriter(synonymFile)) {
            writer.write("# English synonyms test file\n");
            writer.write("running => run, jog, sprint, race\n");
            writer.write("cars => car, automobile, vehicle\n");
            writer.write("books => book, novel, publication, text\n");
            writer.write("studies => study, research, investigation\n");
            writer.write("dogs => dog, canine, hound\n");
            writer.write("playing => play, gaming, recreation\n");
            writer.write("walking => walk, stroll, hike\n");
            writer.write("eating => eat, consume, dine\n");
        }
    }
    
    private void createFrenchSynonyms() throws IOException {
        File synonymFile = tempDir.resolve("french_synonyms.txt").toFile();
        try (FileWriter writer = new FileWriter(synonymFile)) {
            writer.write("# French synonyms test file\n");
            writer.write("coureur => course, sprint, jogging\n");
            writer.write("livres => livre, ouvrage, publication\n");
            writer.write("voitures => voiture, automobile, véhicule\n");
            writer.write("études => étude, recherche, investigation\n");
            writer.write("chiens => chien, canin, animal\n");
            writer.write("jouer => jeu, amusement, récréation\n");
            writer.write("marcher => marche, promenade, randonnée\n");
            writer.write("manger => repas, consommer, dîner\n");
        }
    }
    
    private void createGermanSynonyms() throws IOException {
        File synonymFile = tempDir.resolve("german_synonyms.txt").toFile();
        try (FileWriter writer = new FileWriter(synonymFile)) {
            writer.write("# German synonyms test file\n");
            writer.write("laufen => rennen, joggen, sprint\n");
            writer.write("bücher => buch, werk, publikation\n");
            writer.write("autos => auto, fahrzeug, wagen\n");
            writer.write("studien => studie, forschung, untersuchung\n");
            writer.write("hunde => hund, tier, canine\n");
            writer.write("spielen => spiel, unterhaltung, recreation\n");
            writer.write("gehen => gang, spaziergang, wanderung\n");
            writer.write("essen => mahlzeit, speise, nahrung\n");
        }
    }
    
    private void createRussianSynonyms() throws IOException {
        File synonymFile = tempDir.resolve("russian_synonyms.txt").toFile();
        try (FileWriter writer = new FileWriter(synonymFile)) {
            writer.write("# Russian synonyms test file\n");
            writer.write("бегать => бег, пробежка, спринт\n");
            writer.write("книги => книга, произведение, публикация\n");
            writer.write("машины => машина, автомобиль, транспорт\n");
            writer.write("исследования => исследование, изучение, анализ\n");
            writer.write("собаки => собака, пёс, животное\n");
            writer.write("играть => игра, развлечение, забава\n");
            writer.write("ходить => ходьба, прогулка, поход\n");
            writer.write("есть => еда, питание, трапеза\n");
        }
    }
    
    private void createItalianSynonyms() throws IOException {
        File synonymFile = tempDir.resolve("italian_synonyms.txt").toFile();
        try (FileWriter writer = new FileWriter(synonymFile)) {
            writer.write("# Italian synonyms test file\n");
            writer.write("correre => corsa, jogging, sprint\n");
            writer.write("libri => libro, opera, pubblicazione\n");
            writer.write("macchine => macchina, automobile, veicolo\n");
            writer.write("studi => studio, ricerca, investigazione\n");
            writer.write("cani => cane, animale, bestia\n");
            writer.write("giocare => gioco, divertimento, ricreazione\n");
            writer.write("camminare => camminata, passeggiata, escursione\n");
            writer.write("mangiare => cibo, consumare, pranzo\n");
        }
    }
    
    private void createSpanishSynonyms() throws IOException {
        File synonymFile = tempDir.resolve("spanish_synonyms.txt").toFile();
        try (FileWriter writer = new FileWriter(synonymFile)) {
            writer.write("# Spanish synonyms test file\n");
            writer.write("correr => carrera, jogging, sprint\n");
            writer.write("libros => libro, obra, publicación\n");
            writer.write("coches => coche, automóvil, vehículo\n");
            writer.write("estudios => estudio, investigación, análisis\n");
            writer.write("perros => perro, can, animal\n");
            writer.write("jugar => juego, diversión, recreación\n");
            writer.write("caminar => caminata, paseo, excursión\n");
            writer.write("comer => comida, consumir, almuerzo\n");
        }
    }

    // ===== ENGLISH STEMMING TESTS =====
    
    @Test
    public void testEnglishExactWordMatch() throws SynonymException {
        List<String> synonyms = synonymService.getAllSynonyms("running", "synonyms_en");
        
        assertNotNull(synonyms);
        assertEquals(4, synonyms.size());
        assertTrue(synonyms.contains("run"));
        assertTrue(synonyms.contains("jog"));
        assertTrue(synonyms.contains("sprint"));
        assertTrue(synonyms.contains("race"));
    }

}