package org.egl_cepgl.pm.service;

import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.egl_cepgl.pm.dto.FileDto;
import org.egl_cepgl.pm.dto.ProjectDto;
import org.egl_cepgl.pm.model.File;
import org.egl_cepgl.pm.model.FileCategory;
import org.egl_cepgl.pm.repository.FileCategoryRepository;
import org.egl_cepgl.pm.repository.FileRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
public class FileService
{
    private FileRepository repository;

    private final FileCategoryRepository fileCatRepository;

    private final Path fileStorageLocation;

    private String uploadDir;

    @Autowired
    public FileService(@Value("${file.upload-dir}") String uploadDir, FileRepository repository, FileCategoryRepository fileCatRepository)
    {
        this.repository = repository;
        this.fileCatRepository = fileCatRepository;
        this.uploadDir= uploadDir;

        this.fileStorageLocation = Paths.get(uploadDir)
                .toAbsolutePath().normalize();
        try {
            Files.createDirectories(this.fileStorageLocation);
        } catch (Exception ex) {
            throw new RuntimeException("Could not create the directory where the uploaded files will be stored.", ex);
        }
    }

    public FileDto storeFile(MultipartFile file, Long file_category, Boolean to_notify)
    {
        String fileName = StringUtils.cleanPath(file.getOriginalFilename());
        try {
            if (fileName.contains("..")) {
                throw new RuntimeException("Sorry! Filename contains invalid path sequence " + fileName);
            }
            Path targetLocation = this.fileStorageLocation.resolve(fileName);
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            File file_s= new File();
            file_s.setNamep(file.getOriginalFilename());
            file_s.setPath(uploadDir+'/'+file.getOriginalFilename());
            file_s.setSize(file.getSize());
            file_s.setFormat(StringUtils.getFilenameExtension(file.getOriginalFilename()));
            file_s.setMime_type(file.getContentType());
            if(file_category == 0){
                Optional<FileCategory> fc= fileCatRepository.findByNamep("Fichiers partagés");
                if(fc.isPresent()){
                    file_s.setCategory(fc.get());
                }else{
                    FileCategory nfc= fileCatRepository.save(new FileCategory("Fichiers partagés",""));
                    file_s.setCategory(nfc);
                }
            }else{
                file_s.setCategory(fileCatRepository.findById(file_category).get());
            }
            file_s.setTo_notify(to_notify);
            file_s.setNotified(false);
            File fin_file= repository.save(file_s);
            return FileDto.fromEntity(fin_file);
        } catch (IOException ex) {
            throw new RuntimeException("Could not store file " + fileName + ". Please try again!", ex);
        }
    }

    public Path loadFileAsResource(String fileName) {
        return this.fileStorageLocation.resolve(fileName).normalize();
    }

    public void delete(Long id)
    {
        File file= this.repository.findById(id).orElseThrow();
        try{
            Files.delete(this.fileStorageLocation.resolve(file.getNamep()));
            this.repository.deleteById(id);
        }catch (Exception ex){
            throw new RuntimeException("Could not delete file " + file.getNamep() + ". Please try again!", ex);
        }
    }
}
