package eu.eudat.logic.managers;

import eu.eudat.data.entities.FileUpload;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.logic.proxy.config.configloaders.ConfigLoader;
import eu.eudat.logic.services.ApiContext;
import eu.eudat.logic.services.operations.DatabaseRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Component
public class FileManager {
    private static final Logger logger = LoggerFactory.getLogger(FileManager.class);

    private ApiContext apiContext;
    private DatabaseRepository databaseRepository;
    private Environment environment;

    @Autowired
    public FileManager(ApiContext apiContext, Environment environment) {
        this.apiContext = apiContext;
        this.databaseRepository = apiContext.getOperationsContext().getDatabaseRepository();
        this.environment = environment;
    }

    public String moveFromTmpToStorage(String filename) {
        File tempFile = new File(this.environment.getProperty("temp.temp") + filename);
        File newFile = new File(this.environment.getProperty("file.storage") + filename);
        try {
            return Files.move(tempFile.toPath(), newFile.toPath()).toString();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public boolean deleteFromStorage(String filename) {
        File toBeDeletedFile = new File(this.environment.getProperty("file.storage") + filename);
//            toBeDeletedFile.delete();
        try {
            return Files.deleteIfExists(toBeDeletedFile.toPath());
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;
    }

    public void markOldFileAsDeleted(FileUpload fileUpload) {
        fileUpload.setIsDeleted(true);
        databaseRepository.getFileUploadDao().createOrUpdate(fileUpload);
    }

    public List<FileUpload> getFileUploadsForEntityId(String entityId) {
        return databaseRepository.getFileUploadDao().asQueryable()
                .where((builder, root) -> builder.equal(root.get("entityId"), entityId)).toList();
    }

    public List<FileUpload> getCurrentFileUploadsForEntityId(UUID entityId) {
        return databaseRepository.getFileUploadDao().asQueryable()
                .where((builder, root) -> builder.and(
                        builder.equal(root.get("entityId"), entityId),
                        builder.equal(root.get("isDeleted"), false))).toList();
    }

    public void markAllFilesOfEntityIdAsDeleted(UUID entityId) {
        List<FileUpload> fileUploads = this.getCurrentFileUploadsForEntityId(entityId);
        fileUploads.forEach(fileUpload -> {
            this.markOldFileAsDeleted(fileUpload);
        });
    }

    public void createFile(String id, String fileName, String fileType, String entityId, FileUpload.EntityType entityType, UserInfo userInfo) {
        FileUpload fileUpload = new FileUpload();
        fileUpload.setId(UUID.fromString(id));
        fileUpload.setName(fileName);
        fileUpload.setFileType(fileType);
        fileUpload.setEntityId(UUID.fromString(entityId));
        fileUpload.setEntityType(entityType);
        fileUpload.setCreatedAt(new Date());
        fileUpload.setIsDeleted(false);
        fileUpload.setCreator(userInfo);
        databaseRepository.getFileUploadDao().createOrUpdate(fileUpload);

        this.moveFromTmpToStorage(fileUpload.getId().toString());
    }
}
