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

import dev.fyloz.trial.colorrecipesexplorer.exception.CannotEditDefaultMaterialTypeException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityAlreadyExistsException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.EntityNotFoundException;
import dev.fyloz.trial.colorrecipesexplorer.exception.model.ModelException;
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.dto.MaterialTypeEditorDto;
import dev.fyloz.trial.colorrecipesexplorer.service.model.MaterialTypeJavaService;
import dev.fyloz.trial.colorrecipesexplorer.model.MaterialTypeKt;
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.servlet.ModelAndView;

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

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

    private MaterialTypeJavaService materialTypeService;

    @Autowired
    public MaterialTypeEditorController(MaterialTypeJavaService materialTypeService) {
        this.materialTypeService = materialTypeService;
    }

    @GetMapping(EDITOR_MATERIAL_TYPE)
    public ModelAndView getPage(ModelAndView model) {
        return new ModelResponseBuilder(model)
                .withView(EDITOR_MATERIAL_TYPE)
                .addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAllNotDefault())
                .build();
    }

    @GetMapping(EDITOR_MATERIAL_TYPE_SPECIFIC)
    public ModelAndView getEditPage(ModelAndView model, @PathVariable Long id, MaterialTypeEditorDto materialTypeDto) {
        ModelResponseBuilder responseBuilder = new ModelResponseBuilder(model).withView(EDITOR_MATERIAL_TYPE_EDITOR);

        try {
            if (materialTypeDto.getName() == null) materialTypeDto = new MaterialTypeEditorDto(materialTypeService.getById(id));

            return responseBuilder
                    .addResponseData(ResponseDataType.MATERIAL_TYPE_DTO, materialTypeDto)
                    .build();
        } catch (EntityNotFoundException ex) {
            return getPage(responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_NOT_FOUND, id).build());
        }
    }

    @PostMapping(value = EDITOR_MATERIAL_TYPE, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public ModelAndView updateMaterialType(MaterialTypeEditorDto materialTypeDto) {
        ModelResponseBuilder responseBuilder = new ModelResponseBuilder();

        try {
            materialTypeService.update(materialTypeDto);

            return getPage(responseBuilder.addResponseCode(ResponseCode.SUCCESS_SAVING_MATERIAL_TYPE, materialTypeDto.getMaterialType().getName()).build());
        } catch (EntityNotFoundException ex) {
            return getPage(responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_NOT_FOUND, materialTypeDto.getOldName()).build());
        } catch (EntityAlreadyExistsException ex) {
            if (ModelException.IdentifierType.NAME.equals(ex.getIdentifierType()))
                responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_ALREADY_EXIST, materialTypeDto.getMaterialType().getName());
            else if (MaterialTypeKt.IDENTIFIER_PREFIX_NAME.equals(ex.getIdentifierName()))
                responseBuilder.addResponseCode(ResponseCode.MATERIAL_TYPE_ALREADY_EXIST_PREFIX, materialTypeDto.getMaterialType().getPrefix());
        } catch(CannotEditDefaultMaterialTypeException ex) {
            responseBuilder.addResponseCode(ResponseCode.CANNOT_EDIT_DEFAULT_MATERIAL_TYPE);
        }

        return getEditPage(responseBuilder.build(), materialTypeDto.getMaterialType().getId(), materialTypeDto);
    }
}
