#nullable enable
using Baya.Application.Models.Catalog;
using Baya.Domain.Entities.Catalog;

namespace Baya.Application.Contracts.Persistence;

/// <summary>
/// The admin catalog skeleton (categories → option groups → option values) plus the public browse reads.
/// Reads are projected + no-tracking (callers cache them); admin getters are tracked (include inactive,
/// exclude soft-deleted) for edit/toggle. The applicable-groups read returns a category's own groups
/// <b>plus</b> every cross-category (NULL-category) group — the load-bearing EAV rule.
/// </summary>
public interface ICatalogRepository
{
    /// <summary>All active categories, ordered by sort order — cached by the caller.</summary>
    Task<IReadOnlyList<ServiceCategoryDto>> ListActiveCategoriesAsync(CancellationToken cancellationToken);

    /// <summary>The category's own active groups plus every cross-category (NULL) active group, each with
    /// its active values, ordered by sort order. Empty is valid (no dimensions defined yet).</summary>
    Task<IReadOnlyList<OptionGroupDto>> GetApplicableGroupsAsync(long categoryId, CancellationToken cancellationToken);

    /// <summary>Active-only category projection for variant creation — null if missing or deactivated.</summary>
    Task<ServiceCategoryDto?> GetActiveCategoryAsync(long id, CancellationToken cancellationToken);

    /// <summary>A single group projected with its active values — the honest response for a group mutation
    /// (a freshly created group returns an empty value list). Null if the group is absent/soft-deleted.</summary>
    Task<OptionGroupDto?> GetGroupDtoAsync(long id, CancellationToken cancellationToken);

    // Admin: tracked lookups (include inactive, exclude soft-deleted) for edit/toggle.
    Task<ServiceCategory?> GetCategoryAsync(long id, CancellationToken cancellationToken);
    Task<ServiceOptionGroup?> GetGroupAsync(long id, CancellationToken cancellationToken);
    Task<ServiceOptionValue?> GetValueAsync(long id, CancellationToken cancellationToken);

    /// <summary>Whether a non-soft-deleted category exists (any active state) — parent check for a group.</summary>
    Task<bool> CategoryExistsAsync(long id, CancellationToken cancellationToken);

    /// <summary>Whether a non-soft-deleted group exists — parent check for a value.</summary>
    Task<bool> GroupExistsAsync(long id, CancellationToken cancellationToken);

    Task AddCategoryAsync(ServiceCategory category, CancellationToken cancellationToken);
    Task AddGroupAsync(ServiceOptionGroup group, CancellationToken cancellationToken);
    Task AddValueAsync(ServiceOptionValue value, CancellationToken cancellationToken);
}
