package dev.fyloz.trial.colorrecipesexplorer.web.controller.thymeleaf.editors;

import dev.fyloz.trial.colorrecipesexplorer.exception.SimdutException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ModelResponseBuilder;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseCode;
import dev.fyloz.trial.colorrecipesexplorer.web.response.ResponseDataType;
import dev.fyloz.trial.colorrecipesexplorer.model.Material;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialUpdateDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialJavaService;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import static dev.fyloz.trial.colorrecipesexplorer.web.WebsitePaths.*;

@Controller
@Profile("thymeleaf")
public class MaterialEditorController {

    private MaterialJavaService materialService;
    private MaterialTypeJavaService materialTypeService;

    @Autowired
    public MaterialEditorController(MaterialJavaService materialService, MaterialTypeJavaService materialTypeService) {
        this.materialService = materialService;
        this.materialTypeService = materialTypeService;
    }

    @GetMapping(EDITOR_MATERIAL)
    public ModelAndView getPage(ModelAndView model) {
        return new ModelResponseBuilder(model)
                .withView(EDITOR_MATERIAL)
                .addResponseData(ResponseDataType.MATERIALS, materialService.getAllNotMixType())
                .build();
    }

    @GetMapping(EDITOR_MATERIAL_SPECIFIC)
    public ModelAndView getEditPage(ModelAndView model, @PathVariable Long id, Material material) {
        ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model).withView(EDITOR_MATERIAL_EDITOR);

        try {
            if (material.getName() == null) material = materialService.getById(id);
            return modelResponseBuilder
                    .addResponseData(ResponseDataType.MATERIAL, material)
                    .addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
                    .build();
        } catch (EntityNotFoundException ex) {
            modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, id);
        }

        return getPage(modelResponseBuilder.build());
    }

    @PostMapping(value = EDITOR_MATERIAL, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public ModelAndView updateMaterial(Material material) {
        ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();

        try {
            material = materialService.update(material);

            return getPage(modelResponseBuilder
                    .addResponseCode(ResponseCode.SUCCESS_SAVING_MATERIAL, material.getName())
                    .build());
        } catch (EntityNotFoundException ex) {
            modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, material.getId());
        } catch (EntityAlreadyExistsException ex) {
            modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_ALREADY_EXIST, material.getName());
        }

        return getEditPage(modelResponseBuilder.build(), material.getId(), material);
    }

    @GetMapping(value = EDIT_MATERIAL_SIMDUT_SPECIFIC)
    public ModelAndView getSimdutPage(ModelAndView model, @PathVariable Long id) {
        return new ModelResponseBuilder(model)
                .withView(EDIT_MATERIAL_SIMDUT)
                .addResponseData(ResponseDataType.MATERIAL_ID, id)
                .build();
    }

    @PostMapping(value = EDIT_MATERIAL_SIMDUT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ModelAndView updateSimdut(Long id, MultipartFile simdut) {
        ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder().withRedirect(EDITOR_MATERIAL_SPECIFIC, id);

        try {
            Material material = materialService.getById(id);
            materialService.update(new MaterialUpdateDto(material.getId(), material.getName(), material.getInventoryQuantity(), material.getMaterialType(), simdut));
        } catch (EntityNotFoundException ex) {
            return getSimdutPage(
                    modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, id).build(),
                    id
            );
        } catch (SimdutException ex) {
            modelResponseBuilder.addResponseCode(ResponseCode.ERROR_SAVING_SIMDUT);
        }

        return modelResponseBuilder.build();
    }
}
