package dev.fyloz.trial.colorrecipesexplorer.service.files;

import dev.fyloz.trial.colorrecipesexplorer.exception.SimdutException;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@Service
public class SimdutService {

    private static final String SIMDUT_DIRECTORY = "simdut";

    private FilesService filesService;
    private MaterialJavaService materialService;

    @Autowired
    public SimdutService(FilesService filesService) {
        this.filesService = filesService;
    }

    @Autowired
    @Lazy
    public void setMaterialService(MaterialJavaService materialService) {
        this.materialService = materialService;
    }

    /**
     * Vérifie si un produit a un fichier SIMDUT.
     *
     * @param material Le produit
     * @return Si le produit a un fichier SIMDUT
     */
    public boolean exists(Material material) {
        return filesService.exists(getPath(material));
    }

    /**
     * Vérifie si le produit correspondant à un identifiant a un fichier SIMDUT.
     *
     * @param id L'identifiant du produit
     * @return si le produit correspondant à l'identifiant a un fichier SIMDUT
     */
    public boolean exists(Long id) {
        return exists(materialService.getById(id));
    }

    /**
     * Lit le fichier SIMDUT d'un produit et retourne son contenu.
     *
     * @param material Le produit
     * @return Le contenu du fichier SIMDUT du produit
     */
    public byte[] read(Material material) {
        String path = getPath(material);

        if (!filesService.exists(path)) return new byte[0];

        try {
            return filesService.readAsBytes(path);
        } catch (IOException ex) {
            throw new RuntimeException("Impossible de lire un fichier SIMDUT: " + ex.getMessage());
        }
    }

    /**
     * Lit le fichier SIMDUT du produit correspondant à un identifiant et retourne son contenu.
     *
     * @param id L'identifiant du produit
     * @return Le contenu du fichier SIMDUT du produit correspondant à l'identifiant
     */
    public byte[] read(Long id) {
        return read(materialService.getById(id));
    }

    /**
     * Écrit le fichier SIMDUT d'un produit.
     *
     * @param material Le produit
     * @param simdut   Le contenu du fichier SIMDUT à écrire
     */
    public void write(Material material, MultipartFile simdut) {
        if (!filesService.write(simdut, getPath(material))) throw new SimdutException(material);
    }

    /**
     * Met à jour le fichier SIMDUT d'un produit
     *
     * @param simdut   Le contenu du fichier SIMDUT mis à jour
     * @param material Le produit du SIMDUT
     */
    public void update(MultipartFile simdut, Material material) {
        delete(material);
        write(material, simdut);
    }

    /**
     * Supprime le fichier SIMDUT pour un produit.
     *
     * @param material Le produit
     */
    public void delete(Material material) {
        filesService.delete(getPath(material));
    }

    /**
     * Récupère le chemin vers le fichier SIMDUT d'un produit.
     *
     * @param material Le produit
     * @return Le chemin vers le fichier SIMDUT du produit
     */
    private String getPath(Material material) {
        return filesService.getPath(String.format("%s/%s", SIMDUT_DIRECTORY, getSimdutFileName(material)));
    }

    /**
     * Récupère le nom du fichier SIMDUT d'un produit.
     *
     * @param material Le produit
     * @return Le nom du fichier SIMDUT du produit
     */
    public String getSimdutFileName(Material material) {
        return String.valueOf(material.getId());
    }

}
