package ru.nbch.indicsearchservice.service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import ru.nbch.indicsearchservice.config.settings.ApplicationSettings;
import ru.nbch.indicsearchservice.event.DataSourceChangedEvent;
import ru.nbch.indicsearchservice.model.Settings;
import ru.nbch.indicsearchservice.repository.bank.SettingsMapper;
import ru.nbch.indicsearchservice.util.DataSourceUpdater;

@Service
public class SettingsService {
    private final SettingsMapper settingsMapper;
    private final ApplicationSettings localSettings;
    private final ApplicationEventPublisher publisher;

    public SettingsService(SettingsMapper settingsMapper,
                           ApplicationSettings localSettings,
                           ApplicationEventPublisher publisher) {
        this.settingsMapper = settingsMapper;
        this.localSettings = localSettings;
        this.publisher = publisher;
    }

    public String getSettingsValueByName(String name) {
        return settingsMapper.findByName(name)
            .orElseThrow(() -> new RuntimeException("Setting with key: " + name + " was not found in database!"))
            .getValue();
    }

    public Map<String, Optional<String>> getSettingsValuesByNames(List<String> names) {
        if (names == null || names.isEmpty()) {
            return Map.of();
        }

        List<Settings> foundValues = settingsMapper.findAllByNames(names);
        if (foundValues == null || foundValues.isEmpty()) {
            return Map.of();
        }

        return foundValues.stream().collect(Collectors.toMap(Settings::getName, s -> Optional.ofNullable(s.getValue())));
    }

    public Optional<String> getOptionalSettingsValueByName(String name) {
        return settingsMapper.findByName(name).map(Settings::getValue);
    }

    public void updateLocalSettings() {
        Optional<String> newStorageDirectory = getOptionalSettingsValueByName("indic-search-service-storage"); // todo: change key

        publisher.publishEvent(new DataSourceChangedEvent(DataSourceUpdater.DataSourceType.INDIC));

        if (newStorageDirectory.isPresent()) {
            try {
                Files.createDirectories(Paths.get(newStorageDirectory.get()));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            localSettings.setStorageDirectory(new File(newStorageDirectory.get()));
        }
    }
}
