package de.effigenix.application.inventory;

import de.effigenix.domain.inventory.Stock;
import de.effigenix.domain.inventory.StockBatchId;
import de.effigenix.domain.inventory.StockError;
import de.effigenix.domain.inventory.StockRepository;
import de.effigenix.shared.common.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.LocalDate;
import java.util.List;

public class CheckStockExpiry {

    private static final Logger logger = LoggerFactory.getLogger(CheckStockExpiry.class);

    private final StockRepository stockRepository;

    public CheckStockExpiry(StockRepository stockRepository) {
        this.stockRepository = stockRepository;
    }

    public Result<StockError, ExpiryCheckResult> execute(LocalDate referenceDate) {
        List<Stock> stocks;
        switch (stockRepository.findAllWithExpiryRelevantBatches(referenceDate)) {
            case Result.Failure(var err) ->
                { return Result.failure(new StockError.RepositoryFailure(err.message())); }
            case Result.Success(var val) -> stocks = val;
        }

        int totalExpired = 0;
        int totalExpiringSoon = 0;
        int totalFailed = 0;

        for (Stock stock : stocks) {
            switch (stock.markExpiredBatches(referenceDate)) {
                case Result.Failure(var err) -> { return Result.failure(err); }
                case Result.Success(List<StockBatchId> marked) -> totalExpired += marked.size();
            }

            switch (stock.markExpiringSoonBatches(referenceDate)) {
                case Result.Failure(var err) -> { return Result.failure(err); }
                case Result.Success(List<StockBatchId> marked) -> totalExpiringSoon += marked.size();
            }

            switch (stockRepository.save(stock)) {
                case Result.Failure(var err) -> {
                    totalFailed++;
                    logger.warn("Failed to save stock {} during expiry check: {}", stock.id().value(), err.message());
                }
                case Result.Success(var ignored) -> { }
            }
        }

        return Result.success(new ExpiryCheckResult(totalExpired, totalExpiringSoon, totalFailed));
    }
}
