# ModernMaterialStore.java

    package com.university.bookstore.api;

    import java.util.List;
    import java.util.Optional;
    import java.util.concurrent.CompletableFuture;
    import java.util.function.Predicate;

    import com.university.bookstore.model.Material;
    import com.university.bookstore.model.Media;

    /**
     * Modern interface for polymorphic material store with async operations.
     * Extends the base MaterialStore with modern Java features.
     *
     * @author Navid Mohaghegh
     * @version 4.0
     * @since 2024-09-15
     */
    public interface ModernMaterialStore extends MaterialStore {

        /**
         * Modern InventoryStats using Java record for immutability.
         * Records provide built-in equals(), hashCode(), and toString() methods.
         *
         * @param totalCount total number of materials
         * @param averagePrice average price of all materials
         * @param medianPrice median price of all materials
         * @param uniqueTypes number of unique material types
         * @param mediaCount number of media materials
         * @param printCount number of printed materials
         */
        record ModernInventoryStats(
            int totalCount,
            double averagePrice,
            double medianPrice,
            int uniqueTypes,
            int mediaCount,
            int printCount
        ) {
            /**
             * Compact constructor for validation.
             */
            public ModernInventoryStats {
                if (totalCount < 0) {
                    throw new IllegalArgumentException("Total count cannot be negative");
                }
                if (averagePrice < 0) {
                    throw new IllegalArgumentException("Average price cannot be negative");
                }
                if (medianPrice < 0) {
                    throw new IllegalArgumentException("Median price cannot be negative");
                }
                if (uniqueTypes < 0) {
                    throw new IllegalArgumentException("Unique types cannot be negative");
                }
                if (mediaCount < 0) {
                    throw new IllegalArgumentException("Media count cannot be negative");
                }
                if (printCount < 0) {
                    throw new IllegalArgumentException("Print count cannot be negative");
                }
            }

            /**
             * Creates an empty stats instance.
             *
             * @return stats with all zero values
             */
            public static ModernInventoryStats empty() {
                return new ModernInventoryStats(0, 0, 0, 0, 0, 0);
            }

            /**
             * Checks if the inventory is empty.
             *
             * @return true if total count is zero
             */
            public boolean isEmpty() {
                return totalCount == 0;
            }

            /**
             * Gets the percentage of media materials.
             *
             * @return media percentage (0-100)
             */
            public double getMediaPercentage() {
                return totalCount > 0 ? (mediaCount * 100.0) / totalCount : 0;
            }

            /**
             * Gets the percentage of print materials.
             *
             * @return print percentage (0-100)
             */
            public double getPrintPercentage() {
                return totalCount > 0 ? (printCount * 100.0) / totalCount : 0;
            }

            /**
             * Creates a summary string for reporting.
             *
             * @return formatted summary
             */
            public String getSummary() {
                return String.format(
                    """
                    Inventory Statistics:
                    - Total Items: %d
                    - Average Price: $%.2f
                    - Median Price: $%.2f
                    - Unique Types: %d
                    - Media Materials: %d (%.1f%%)
                    - Print Materials: %d (%.1f%%)
                    """,
                    totalCount, averagePrice, medianPrice, uniqueTypes,
                    mediaCount, getMediaPercentage(),
                    printCount, getPrintPercentage()
                );
            }
        }

        /**
         * Batch operation result record.
         *
         * @param successful number of successful operations
         * @param failed number of failed operations
         * @param errors list of error messages
         */
        record BatchOperationResult(
            int successful,
            int failed,
            List<String> errors
        ) {
            /**
             * Checks if all operations were successful.
             *
             * @return true if no failures
             */
            public boolean isCompleteSuccess() {
                return failed == 0 && (errors == null || errors.isEmpty());
            }

            /**
             * Gets the total number of operations.
             *
             * @return sum of successful and failed
             */
            public int totalOperations() {
                return successful + failed;
            }

            /**
             * Gets the success rate.
             *
             * @return success percentage (0-100)
             */
            public double successRate() {
                int total = totalOperations();
                return total > 0 ? (successful * 100.0) / total : 0;
            }
        }

        /**
         * Search criteria record for complex searches.
         *
         * @param title optional title search term
         * @param creator optional creator search term
         * @param type optional material type filter
         * @param minPrice optional minimum price
         * @param maxPrice optional maximum price
         * @param yearFrom optional start year
         * @param yearTo optional end year
         */
        record SearchCriteria(
            Optional<String> title,
            Optional<String> creator,
            Optional<Material.MaterialType> type,
            Optional<Double> minPrice,
            Optional<Double> maxPrice,
            Optional<Integer> yearFrom,
            Optional<Integer> yearTo
        ) {
            /**
             * Builder for SearchCriteria.
             */
            public static class Builder {
                private Optional<String> title = Optional.empty();
                private Optional<String> creator = Optional.empty();
                private Optional<Material.MaterialType> type = Optional.empty();
                private Optional<Double> minPrice = Optional.empty();
                private Optional<Double> maxPrice = Optional.empty();
                private Optional<Integer> yearFrom = Optional.empty();
                private Optional<Integer> yearTo = Optional.empty();

                public Builder withTitle(String title) {
                    this.title = Optional.ofNullable(title);
                    return this;
                }

                public Builder withCreator(String creator) {
                    this.creator = Optional.ofNullable(creator);
                    return this;
                }

                public Builder withType(Material.MaterialType type) {
                    this.type = Optional.ofNullable(type);
                    return this;
                }

                public Builder withPriceRange(Double min, Double max) {
                    this.minPrice = Optional.ofNullable(min);
                    this.maxPrice = Optional.ofNullable(max);
                    return this;
                }

                public Builder withYearRange(Integer from, Integer to) {
                    this.yearFrom = Optional.ofNullable(from);
                    this.yearTo = Optional.ofNullable(to);
                    return this;
                }

                public SearchCriteria build() {
                    return new SearchCriteria(
                        title, creator, type,
                        minPrice, maxPrice,
                        yearFrom, yearTo
                    );
                }
            }

            /**
             * Creates a new builder.
             *
             * @return new builder instance
             */
            public static Builder builder() {
                return new Builder();
            }

            /**
             * Checks if any criteria is specified.
             *
             * @return true if at least one criterion is present
             */
            public boolean hasAnyCriteria() {
                return title.isPresent() || creator.isPresent() || type.isPresent() ||
                       minPrice.isPresent() || maxPrice.isPresent() ||
                       yearFrom.isPresent() || yearTo.isPresent();
            }
        }

        // Async operation methods

        /**
         * Adds material asynchronously.
         *
         * @param material the material to add
         * @return CompletableFuture with the result
         */
        CompletableFuture<Boolean> addMaterialAsync(Material material);

        /**
         * Finds material by ID asynchronously.
         *
         * @param id the material ID
         * @return CompletableFuture with the result
         */
        CompletableFuture<Optional<Material>> findByIdAsync(String id);

        /**
         * Searches by title asynchronously.
         *
         * @param title the title to search for
         * @return CompletableFuture with the results
         */
        CompletableFuture<List<Material>> searchByTitleAsync(String title);

        /**
         * Gets inventory statistics asynchronously.
         *
         * @return CompletableFuture with the statistics
         */
        CompletableFuture<ModernInventoryStats> getModernInventoryStatsAsync();

        /**
         * Performs advanced search with multiple criteria.
         *
         * @param criteria the search criteria
         * @return CompletableFuture with matching materials
         */
        CompletableFuture<List<Material>> advancedSearchAsync(SearchCriteria criteria);

        /**
         * Adds multiple materials in batch.
         *
         * @param materials collection of materials to add
         * @return CompletableFuture with batch operation result
         */
        CompletableFuture<BatchOperationResult> addMaterialsBatchAsync(List<Material> materials);

        /**
         * Removes multiple materials in batch.
         *
         * @param ids collection of IDs to remove
         * @return CompletableFuture with batch operation result
         */
        CompletableFuture<BatchOperationResult> removeMaterialsBatchAsync(List<String> ids);
    }