package it.powerbyte.springbootstarter.service;

import it.powerbyte.springbootstarter.entity.FileStorage;
import it.powerbyte.springbootstarter.repository.FileStorageRepository;
import lombok.AllArgsConstructor;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.stereotype.Service;
import org.springframework.util.FileSystemUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

@Service
@AllArgsConstructor
public class FilesStorageServiceImpl implements FilesStorageService {

    private final FileStorageRepository fileStorageRepository;
    private final Path root = Paths.get("/tmp/uploads");


    public void init() {
        try {
            Files.createDirectory(root);
        } catch (IOException e) {
            throw new RuntimeException("Could not initialize folder for upload!");
        }
    }


    public void save(Long ownerId, MultipartFile file) {
        try {
            FileStorage fs = new FileStorage();
            fs.setOwnerId(ownerId);
            fs.setFileName(file.getOriginalFilename());
            fs.setContentType(file.getContentType());
            fs.setUrl(file.getName());
            fs.setFile(file.getBytes());
            fileStorageRepository.save(fs);

        } catch (Exception e) {
            throw new RuntimeException("Could not store the file. Error: " + e.getMessage());
        }
    }

    @Override
    public List<FileStorage> findByOwnerId(Long ownerId) {
        return fileStorageRepository.findByOwnerId(ownerId);
    }

    public void save(MultipartFile file) {
        try {
            Files.copy(file.getInputStream(), this.root.resolve(file.getOriginalFilename()));
        } catch (Exception e) {
            throw new RuntimeException("Could not store the file. Error: " + e.getMessage());
        }
    }


    public FileStorage load(Long  id) {
        try {
            Optional<FileStorage> fs = fileStorageRepository.findById(id);
            Resource resource = new UrlResource(fs.get().getFileName());

            if (fs.isPresent()){
                return fs.get();
            } else {
                throw new RuntimeException("File non trovato!");
            }


        } catch (MalformedURLException e) {
            throw new RuntimeException("Error: " + e.getMessage());
        }
    }

    public Resource load(String filename) {
        try {
            Path file = root.resolve(filename);
            Resource resource = new UrlResource(file.toUri());

            if (resource.exists() || resource.isReadable()) {
                return resource;
            } else {
                throw new RuntimeException("Could not read the file!");
            }
        } catch (MalformedURLException e) {
            throw new RuntimeException("Error: " + e.getMessage());
        }
    }


    public void deleteAll() {
        FileSystemUtils.deleteRecursively(root.toFile());
    }


    public Stream<Path> loadAll() {

        try {
            return Files.walk(this.root, 1).filter(path -> !path.equals(this.root)).map(this.root::relativize);
        } catch (IOException e) {
            throw new RuntimeException("Could not load the files!");
        }
    }
}
