package org.jabref.logic.cleanup;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Supplier;

import org.jabref.logic.FilePreferences;
import org.jabref.logic.JabRefException;
import org.jabref.logic.externalfiles.LinkedFileHandler;
import org.jabref.logic.l10n.Localization;
import org.jabref.model.FieldChange;
import org.jabref.model.database.BibDatabaseContext;
import org.jabref.model.entry.BibEntry;
import org.jabref.model.entry.LinkedFile;

import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/// Moves the file into the default file directory. Does *not* rename the file.
public class MoveFilesCleanup implements CleanupJob {

    private static final Logger LOGGER = LoggerFactory.getLogger(MoveFilesCleanup.class);

    private final Supplier<BibDatabaseContext> databaseContext;
    private final FilePreferences filePreferences;
    private final List<JabRefException> ioExceptions;

    public MoveFilesCleanup(@NonNull Supplier<BibDatabaseContext> databaseContext,
                            @NonNull FilePreferences filePreferences) {
        this.databaseContext = databaseContext;
        this.filePreferences = filePreferences;
        this.ioExceptions = new ArrayList<>();
    }

    @Override
    public List<FieldChange> cleanup(BibEntry entry, Consumer<Runnable> mutationScheduler) {
        List<LinkedFile> files = entry.getFiles();

        boolean changed = false;
        for (LinkedFile file : files) {
            LinkedFileHandler fileHandler = new LinkedFileHandler(file, entry, databaseContext.get(), filePreferences);
            try {
                changed = fileHandler.moveToDefaultDirectory() || changed;
            } catch (IOException exception) {
                LOGGER.error("Error while moving file {}", file.getLink(), exception);
                ioExceptions.add(new JabRefException(Localization.lang("Could not move file %0. Please close this file and retry.", file.getLink()), exception));
            }
        }

        if (changed) {
            return FileFieldCleanupUpdater.updateFileField(entry, files, mutationScheduler);
        }

        return List.of();
    }

    @Override
    public List<FieldChange> cleanup(BibEntry entry) {
        return cleanup(entry, Runnable::run);
    }

    public List<JabRefException> getIoExceptions() {
        return ioExceptions;
    }
}
