package com.bookshop.behavioral.templatemethod;

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

import com.bookshop.domain.Book;
import java.math.BigDecimal;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

@DisplayName("Template Method -- one report skeleton, many output formats")
class SalesReportTest {

    private final List<Book> sales = List.of(
            new Book("978-0132350884", "Clean Code", "Robert C. Martin", new BigDecimal("32.50")),
            new Book("978-0134685991", "Effective Java", "Joshua Bloch", new BigDecimal("39.99")));

    @Test
    @DisplayName("the CSV report fills the skeleton with CSV formatting")
    void csvReport() {
        String report = new CsvSalesReport().generate(sales);

        assertEquals("""
                title,author,price
                Clean Code,Robert C. Martin,32.50
                Effective Java,Joshua Bloch,39.99
                total,,72.49
                """, report);
    }

    @Test
    @DisplayName("the HTML report reuses the identical skeleton and totalling logic")
    void htmlReport() {
        String report = new HtmlSalesReport().generate(sales);

        assertTrue(report.startsWith("<table><tr><th>Title</th>"));
        assertTrue(report.contains("<td>Clean Code</td>"));
        assertTrue(report.endsWith("<tr><td>Total</td><td>72.49</td></tr></table>"));
    }

    @Test
    @DisplayName("both formats agree on the total because the calculation exists exactly once")
    void totalsCannotDrift() {
        assertTrue(new CsvSalesReport().generate(sales).contains("72.49"));
        assertTrue(new HtmlSalesReport().generate(sales).contains("72.49"));
    }
}
