package de.effigenix.domain.masterdata.productcategory;

import de.effigenix.shared.common.Result;

import static de.effigenix.shared.common.Result.*;

/**
 * Mini-Aggregate for product categories.
 * DB-based entity, dynamically extendable by users.
 */
public class ProductCategory {

    private final ProductCategoryId id;
    private CategoryName name;
    private String description;

    private ProductCategory(ProductCategoryId id, CategoryName name, String description) {
        this.id = id;
        this.name = name;
        this.description = description;
    }

    /**
     * Factory: Erzeugt eine neue ProductCategory aus rohen Eingaben.
     * Orchestriert Validierung des CategoryName-VO intern.
     */
    public static Result<ProductCategoryError, ProductCategory> create(ProductCategoryDraft draft) {
        CategoryName name;
        switch (CategoryName.of(draft.name())) {
            case Failure(var msg) -> { return Result.failure(new ProductCategoryError.ValidationFailure(msg)); }
            case Success(var val) -> name = val;
        }
        return Result.success(new ProductCategory(ProductCategoryId.generate(), name, draft.description()));
    }

    public static ProductCategory reconstitute(ProductCategoryId id, CategoryName name, String description) {
        return new ProductCategory(id, name, description);
    }

    /**
     * Wendet partielle Updates an. Das Aggregate validiert intern.
     * null-Felder im Draft werden ignoriert.
     */
    public Result<ProductCategoryError, Void> update(ProductCategoryUpdateDraft draft) {
        if (draft.name() != null) {
            switch (CategoryName.of(draft.name())) {
                case Failure(var msg) -> { return Result.failure(new ProductCategoryError.ValidationFailure(msg)); }
                case Success(var val) -> this.name = val;
            }
        }
        if (draft.description() != null) {
            this.description = draft.description();
        }
        return Result.success(null);
    }

    public ProductCategoryId id() { return id; }
    public CategoryName name() { return name; }
    public String description() { return description; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (!(obj instanceof ProductCategory other)) return false;
        return id.equals(other.id);
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }

    @Override
    public String toString() {
        return "ProductCategory{id=" + id + ", name=" + name + "}";
    }
}
