package kz.konturai.parser.service;

import kz.konturai.parser.dto.ParserResultDto;
import kz.konturai.parser.model.MarketItem;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * Сервис для управления всеми парсерами.
 * Использует паттерн "Фасад" для упрощения работы с парсерами.
 */
@Service
public class ParserManagerService {

    private static final Logger logger = LoggerFactory.getLogger(ParserManagerService.class);

    private final Map<String, ParserService> parsers;
    private final MarketItemService marketItemService;

    // Spring автоматически инжектирует все бины типа ParserService
    public ParserManagerService(List<ParserService> parserServices, MarketItemService marketItemService) {
        this.parsers = parserServices.stream()
                .collect(Collectors.toMap(ParserService::getSourceName, service -> service));
        this.marketItemService = marketItemService;

        logger.info("Инициализирован ParserManagerService с {} парсерами: {}",
                parsers.size(), parsers.keySet());
    }

    /**
     * Запускает парсер по его имени.
     * 
     * @param sourceName Имя источника (например, "kursiv")
     * @return Результат парсинга
     */
    public List<MarketItem> runParser(String sourceName) {
        ParserService parser = Optional.ofNullable(parsers.get(sourceName))
                .orElseThrow(() -> new IllegalArgumentException("Парсер не найден: " + sourceName));

        logger.info("Запуск парсера: {}", sourceName);
        return parser.parseAndSaveRssFeed();
    }

    /**
     * Асинхронно запускает все парсеры.
     * 
     * @return Список результатов для каждого парсера
     */
    @Async
    public CompletableFuture<List<ParserResultDto>> runAllParsers() {
        logger.info("Запуск всех парсеров асинхронно");

        long totalItemsBefore = marketItemService.getTotalItemsCount();

        List<ParserResultDto> results = parsers.values().parallelStream()
                .map(parser -> {
                    try {
                        logger.debug("Запуск парсера: {}", parser.getSourceName());
                        List<MarketItem> savedItems = parser.parseAndSaveRssFeed();
                        long totalItemsAfter = marketItemService.getTotalItemsCount();

                        ParserResultDto result = new ParserResultDto(
                                parser.getSourceName(),
                                savedItems.size(),
                                totalItemsAfter,
                                "completed");

                        logger.debug("Парсер {} завершен. Обработано записей: {}",
                                parser.getSourceName(), savedItems.size());

                        return result;
                    } catch (Exception e) {
                        logger.error("Ошибка при запуске парсера {}: {}", parser.getSourceName(), e.getMessage(), e);
                        return new ParserResultDto(
                                parser.getSourceName(),
                                0,
                                totalItemsBefore,
                                "error: " + e.getMessage());
                    }
                })
                .collect(Collectors.toList());

        logger.info("Все парсеры завершены. Результатов: {}", results.size());
        return CompletableFuture.completedFuture(results);
    }

    /**
     * Получает список доступных парсеров.
     * 
     * @return Список имен парсеров
     */
    public List<String> getAvailableParsers() {
        return parsers.keySet().stream().sorted().collect(Collectors.toList());
    }

    /**
     * Проверяет, существует ли парсер с указанным именем.
     * 
     * @param sourceName Имя источника
     * @return true, если парсер существует
     */
    public boolean hasParser(String sourceName) {
        return parsers.containsKey(sourceName);
    }

    /**
     * Получает количество зарегистрированных парсеров.
     * 
     * @return Количество парсеров
     */
    public int getParserCount() {
        return parsers.size();
    }
}
