package shop;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.extension.ExtendWith;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.math.BigDecimal;
import java.time.Duration;

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

/**
 * The same six checks after the repair pass: locate by data-testid (the contract the app team promises to keep),
 * wait for the condition instead of sleeping, and compare a price as a number rather than as a string.
 */
@ExtendWith(BrowserSupport.ResultLog.class)
class RepairedTest {

    static ShopServer shop;
    WebDriver driver;
    WebDriverWait wait;

    @BeforeAll
    static void startShop() throws Exception { shop = new ShopServer(); }

    @BeforeEach
    void open() {
        driver = BrowserSupport.newDriver();
        wait = new WebDriverWait(driver, Duration.ofSeconds(5));
        driver.get(shop.url(BrowserSupport.version()));
    }

    @AfterEach
    void close() { driver.quit(); }

    private static By id(String testId) { return By.cssSelector("[data-testid='" + testId + "']"); }

    private void cartShows(String count) {
        wait.until(ExpectedConditions.textToBe(id("cart-count"), count));
    }

    @RepeatedTest(5)
    void addFirstProductShowsOneInCart() {
        driver.findElement(id("add-notebook")).click();
        cartShows("1");
    }

    @RepeatedTest(5)
    void addTwoProductsShowsTwoInCart() {
        driver.findElement(id("add-notebook")).click();
        driver.findElement(id("add-pen")).click();
        cartShows("2");
    }

    @RepeatedTest(5)
    void searchingForPenLeavesOneProduct() {
        driver.findElement(id("search")).sendKeys("Pen");
        wait.until(d -> d.findElements(By.cssSelector("[data-testid^='product-']")).stream()
                .filter(WebElement::isDisplayed).count() == 1);
    }

    @RepeatedTest(5)
    void notebookCosts120Rupees() {
        String text = driver.findElement(id("price-notebook")).getText();
        assertEquals(0, new BigDecimal("120").compareTo(new BigDecimal(text.replaceAll("[^0-9.]", ""))), text);
    }

    @RepeatedTest(5)
    void addingThePenThreeTimesShowsThree() {
        WebElement add = driver.findElement(id("add-pen"));
        add.click();
        add.click();
        add.click();
        cartShows("3");
    }

    @RepeatedTest(5)
    void emptySearchShowsAllThreeProducts() {
        assertEquals(3, driver.findElements(By.cssSelector("[data-testid^='product-']")).size());
    }
}
