package com.bookshop.solid.ocp;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

@DisplayName("OCP -- new shipping options are added, never edited in")
class ShippingQuotesOcpTest {

    @Test
    @DisplayName("the calculator quotes every registered rate without knowing any of them")
    void quotesAllRegisteredRates() {
        ShippingQuotes quotes = new ShippingQuotes(List.of(new StandardShipping(), new ExpressShipping()));

        Map<String, BigDecimal> forSmallOrder = quotes.quoteAll(new BigDecimal("10.00"));

        assertEquals(new BigDecimal("3.00"), forSmallOrder.get("standard"));
        assertEquals(new BigDecimal("7.50"), forSmallOrder.get("express"));
    }

    @Test
    @DisplayName("extension in action: a brand-new rate joins with zero changes to ShippingQuotes")
    void newRateRequiresNoModification() {
        ShippingRate droneDelivery = new ShippingRate() {
            @Override
            public String name() {
                return "drone";
            }

            @Override
            public BigDecimal costFor(BigDecimal orderTotal) {
                return new BigDecimal("15.00");
            }
        };
        ShippingQuotes quotes = new ShippingQuotes(List.of(new StandardShipping(), droneDelivery));

        Map<String, BigDecimal> result = quotes.quoteAll(new BigDecimal("30.00"));

        assertEquals(BigDecimal.ZERO, result.get("standard"));
        assertEquals(new BigDecimal("15.00"), result.get("drone"));
    }
}
