package com.clanstop.healing.driver;

import com.clanstop.healing.locator.LocatorResolver;
import com.clanstop.healing.persistence.ElementStore;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.List;

/**
 * A thin, lightweight facade over a real {@link WebDriver}. Rather than re-implementing the
 * full WebDriver interface, it exposes the handful of methods tests need and routes element
 * lookups through {@link LocatorResolver} so healing is transparent to step code. Anything
 * else is reachable via {@link #raw()}.
 */
public final class HealingDriver {

    private final WebDriver delegate;
    private final LocatorResolver resolver;

    public HealingDriver(WebDriver delegate) {
        this.delegate = delegate;
        this.resolver = new LocatorResolver(delegate, new ElementStore());
        // Register for failure screenshots taken by the step-logging plugin.
        HealingContext.setCurrentDriver(delegate);
    }

    /**
     * Find an element by its logical key and primary locator. On a primary miss the resolver
     * heals within this same call, so the caller simply receives a usable element (or a
     * {@code NoSuchElementException} if healing also fails).
     */
    public WebElement find(ByKey key, By primary) {
        return resolver.find(key.value(), primary);
    }

    /** Convenience: derive the logical key from the locator itself. */
    public WebElement find(By primary) {
        return resolver.find(primary.toString(), primary);
    }

    public List<WebElement> findAll(By by) {
        return delegate.findElements(by);
    }

    public void get(String url) {
        delegate.get(url);
    }

    public String getCurrentUrl() {
        return delegate.getCurrentUrl();
    }

    public String getTitle() {
        return delegate.getTitle();
    }

    /** Escape hatch for anything the facade does not wrap (waits, alerts, windows, JS, ...). */
    public WebDriver raw() {
        return delegate;
    }

    public void quit() {
        delegate.quit();
    }
}
