package kz.konturai.parser.service;

import kz.konturai.parser.model.MarketItem;
import kz.konturai.parser.repository.MarketItemRepository;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.TestPropertySource;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;

import java.util.List;

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

@SpringBootTest
@EnabledIfEnvironmentVariable(named = "RUN_INTEGRATION_TESTS", matches = "true")
@TestPropertySource(properties = {
        "spring.data.mongodb.host=${MONGODB_HOST:localhost}",
        "spring.data.mongodb.port=${MONGODB_PORT:27017}",
        "spring.data.mongodb.database=parser_test_db",
        "rss.kapital.url=https://kapital.kz/rss/"
})
public class KapitalParserServiceTest {

    @Autowired
    private KapitalParserService kapitalParserService;

    @Autowired
    private MarketItemRepository marketItemRepository;

    @Test
    public void testParseAndSaveRssFeed() {
        // Очищаем базу данных перед тестом
        marketItemRepository.deleteAll();

        // Запускаем парсинг
        List<MarketItem> savedItems = kapitalParserService.parseAndSaveRssFeed();

        // Проверяем результаты
        assertNotNull(savedItems, "Список сохраненных элементов не должен быть null");

        // Проверяем, что хотя бы одна запись была обработана
        assertTrue(savedItems.size() > 0, "Должна быть обработана хотя бы одна запись из Kapital.kz");

        // Проверяем структуру первой записи
        MarketItem firstItem = savedItems.get(0);
        assertNotNull(firstItem.getTitle(), "Заголовок не должен быть null");
        assertNotNull(firstItem.getUrl(), "URL не должен быть null");
        assertNotNull(firstItem.getHash(), "Хэш не должен быть null");
        assertNotNull(firstItem.getPublishedAt(), "Дата публикации не должна быть null");
        assertNotNull(firstItem.getRawText(), "Текст не должен быть null");
        assertEquals("Kapital.kz (Бизнес)", firstItem.getSourceName(),
                "Название источника должно быть Kapital.kz (Бизнес)");
        assertEquals("Бизнес", firstItem.getCategory(), "Категория должна быть Бизнес");

        // Проверяем, что запись сохранилась в базе данных
        long totalCount = marketItemRepository.count();
        assertTrue(totalCount > 0, "В базе данных должны быть записи");

        // Проверяем дедупликацию - повторный запуск не должен создавать дубликаты
        List<MarketItem> secondRun = kapitalParserService.parseAndSaveRssFeed();
        long secondCount = marketItemRepository.count();

        // Количество записей должно остаться тем же или увеличиться незначительно
        assertTrue(secondCount >= totalCount, "Количество записей не должно уменьшиться");

        System.out.println("Тест KapitalParserService прошел успешно:");
        System.out.println("- Обработано записей в первом запуске: " + savedItems.size());
        System.out.println("- Обработано записей во втором запуске: " + secondRun.size());
        System.out.println("- Общее количество записей в БД: " + secondCount);
    }

    @Test
    public void testScheduledMethodExists() {
        // Проверяем, что метод scheduledParseAndStoreNews существует и доступен
        assertDoesNotThrow(() -> {
            // Используем рефлексию для проверки существования метода
            kapitalParserService.getClass().getMethod("scheduledParseAndStoreNews");
        }, "Метод scheduledParseAndStoreNews должен существовать");
    }

    @Test
    public void testScheduledMethodCanBeCalled() {
        // Проверяем, что метод можно вызвать без ошибок
        assertDoesNotThrow(() -> {
            kapitalParserService.scheduledParseAndStoreNews();
        }, "Метод scheduledParseAndStoreNews должен выполняться без ошибок");
    }

    @Test
    public void testGetKapitalItemsCount() {
        long count = kapitalParserService.getKapitalItemsCount();
        assertTrue(count >= 0, "Количество записей должно быть неотрицательным");
    }

    @Test
    public void testGetAllKapitalItems() {
        List<MarketItem> items = kapitalParserService.getAllKapitalItems();
        assertNotNull(items, "Список элементов не должен быть null");

        // Проверяем структуру элементов
        for (MarketItem item : items) {
            assertNotNull(item.getId(), "ID элемента не должен быть null");
            assertNotNull(item.getHash(), "Хэш элемента не должен быть null");
            assertNotNull(item.getSourceName(), "Название источника не должно быть null");
        }
    }
}
