package org.jabref.logic.ai.util;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.jabref.logic.util.NotificationService;

import org.h2.mvstore.MVStore;
import org.h2.mvstore.MVStoreException;
import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/// This is a base class for the AI artifacts (summaries, chat messages, etc.).
/// It sets up and wraps an [MVStore], and also provides a way to load an *in-memory* storage in case there are problems while initializing the on-disk version.
/// It also uses a [NotificationService] to notify the user about errors.
public abstract class MVStoreBase implements AutoCloseable {
    private static final Logger LOGGER = LoggerFactory.getLogger(MVStoreBase.class);

    protected MVStore mvStore;

    public MVStoreBase(@NonNull Path path, NotificationService dialogService) {
        Path mvStorePath = path;

        if (path.getParent() != null) {
            try {
                Files.createDirectories(path.getParent());
            } catch (IOException e) {
                LOGGER.error(errorMessageForOpening(), e);
                dialogService.notify(errorMessageForOpeningLocalized());
                mvStorePath = null;
            }
        }

        try {
            this.mvStore = new MVStore.Builder()
                    .autoCommitDisabled()
                    .fileName(mvStorePath == null ? null : mvStorePath.toString())
                    .open();
        } catch (MVStoreException e) {
            this.mvStore = openInMemoryStore();
            LOGGER.error(errorMessageForOpening(), e);
        }
    }

    protected MVStoreBase() {
        this.mvStore = openInMemoryStore();
    }

    private MVStore openInMemoryStore() {
        return new MVStore.Builder()
                .autoCommitDisabled()
                .fileName(null) // creates an in memory store
                .open();
    }

    public void commit() {
        if (mvStore != null) {
            mvStore.commit();
        }
    }

    public void close() {
        if (mvStore != null) {
            mvStore.close();
        }
    }

    protected abstract String errorMessageForOpening();

    protected abstract String errorMessageForOpeningLocalized();
}
