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

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.Mix;
import dev.fyloz.trial.colorrecipesexplorer.model.MixType;
import dev.fyloz.trial.colorrecipesexplorer.model.Recipe;
import dev.fyloz.trial.colorrecipesexplorer.model.dto.MixFormDto;
import dev.fyloz.trial.colorrecipesexplorer.service.ServiceKt;
import dev.fyloz.trial.colorrecipesexplorer.service.model.*;
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.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.servlet.ModelAndView;

import javax.validation.Valid;

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

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

    private MixService mixService;
    private RecipeService recipeService;
    private MaterialJavaService materialService;
    private MaterialTypeJavaService materialTypeService;

    @Autowired
    public MixCreatorController(MixService mixService, RecipeService recipeService, MaterialJavaService materialService, MixTypeService mixTypeService, MaterialTypeJavaService materialTypeService) {
        this.mixService = mixService;
        this.recipeService = recipeService;
        this.materialService = materialService;
        this.materialTypeService = materialTypeService;
    }

    @GetMapping(CREATOR_MIX_SPECIFIC)
    public ModelAndView getPage(ModelAndView model, @PathVariable Long id) {
        ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder(model)
                .withView(CREATOR_MIX);

        try {
            Recipe recipe = recipeService.getById(id);

            modelResponseBuilder
                    .addResponseData(ResponseDataType.RECIPE, recipe)
                    .addResponseData(ResponseDataType.MATERIAL_TYPES, materialTypeService.getAll())
                    .addResponseData(ResponseDataType.MATERIALS_JSON, ServiceKt.asJson(mixService.getAvailableMaterialsForNewMix(recipe)));

            if (materialService.getAll().isEmpty())
                modelResponseBuilder.addResponseData(ResponseDataType.BLOCK_BUTTON, true);
        } catch (EntityNotFoundException ex) {
            modelResponseBuilder
                    .withRedirect(EDITOR_RECIPE);
        }

        return modelResponseBuilder.build();
    }

    @PostMapping(value = CREATOR_MIX, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public ModelAndView createMix(@ModelAttribute @Valid MixFormDto formDto) {
        ModelResponseBuilder modelResponseBuilder = new ModelResponseBuilder();

        try {
            mixService.save(formDto);

            return modelResponseBuilder
                    .withRedirect(EDITOR_RECIPE_SPECIFIC, formDto.getRecipe().getId())
                    .build();
        } catch (EntityNotFoundException ex) {
            modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_NOT_FOUND, ex.getRequestedId());
        } catch (EntityAlreadyExistsException ex) {
            if (ex.getIdentifierName().equals(Mix.IDENTIFIER_MIX_TYPE_NAME))
                modelResponseBuilder.addResponseCode(ResponseCode.MIX_TYPE_ALREADY_USED, ex.getRequestedId());
            else if (ex.getIdentifierName().equals(MixType.IDENTIFIER_MATERIAL_NAME))
                modelResponseBuilder.addResponseCode(ResponseCode.MATERIAL_AND_MIX_TYPE_CANNOT_HAVE_SAME_NAME);
        }

        return getPage(modelResponseBuilder.build(), formDto.getRecipe().getId());
    }
}
