package dev.fyloz.trial.colorrecipesexplorer.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.hibernate.validator.constraints.Length;
import org.jetbrains.annotations.Nullable;

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;

@Entity
@Data
@RequiredArgsConstructor
@NoArgsConstructor
public class Recipe implements Model {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;

    @NonNull
    @NotNull
    @Length(min = 2)
    private String name;

    @NonNull
    @NotNull
    @ManyToOne
    private Company company;

    @NonNull
    @NotNull
    private String description;

    @NonNull
    @NotNull
    private Integer sample;

    private String approbationDate;

    private String remark;

    private String note;

    @JsonIgnore
    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL)
    private List<Mix> mixes;

    @OneToMany(mappedBy = "recipe", cascade = CascadeType.ALL)
    private List<RecipeStep> recipeSteps;

    public Recipe(Long id, String name, Company company, String description, Integer sample, String approbationDate, String remark, String note) {
        this.id = id;
        this.name = name;
        this.company = company;
        this.description = description;
        this.sample = sample;
        this.approbationDate = approbationDate;
        this.remark = remark;
        this.note = note;
    }

    /**
     * Récupère les mélanges triés par leur identifiant.
     *
     * @return Les mélanges triés par leur identifiant
     */
    @JsonIgnore
    public List<Mix> getMixesSortedById() {
        List<Mix> sortedMixes = new ArrayList<>(mixes);
        sortedMixes.sort(Comparator.comparing(Mix::getId));
        return sortedMixes;
    }

    /**
     * Récupère les types de mélange des mélanges de la recette.
     *
     * @return Les types de mélange contenus dans la recette
     */
    @JsonIgnore
    public Collection<MixType> getMixTypes() {
        return mixes.stream()
                .map(Mix::getMixType)
                .collect(Collectors.toList());
    }

    /**
     * Vérifie si la recette contient un type de mélange.
     *
     * @param mixType Le type de mélange
     * @return Si la recette contient le type de mélange
     */
    @JsonIgnore
    public boolean hasMixType(MixType mixType) {
        return getMixTypes().contains(mixType);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Recipe recipe = (Recipe) o;
        return Objects.equals(name, recipe.name) &&
                Objects.equals(company, recipe.company);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, company);
    }
}
