package de.avatic.lcc.e2e.config;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserContext;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;

import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.logging.Logger;

/**
 * Configuration and factory class for Playwright browser instances.
 * Provides centralized configuration for E2E tests.
 */
public class PlaywrightTestConfiguration {

    private static final Logger logger = Logger.getLogger(PlaywrightTestConfiguration.class.getName());

    // Default configuration values
    public static final String DEFAULT_BASE_URL = "http://localhost:5173";
    public static final boolean DEFAULT_HEADLESS = true;
    public static final int DEFAULT_VIEWPORT_WIDTH = 1920;
    public static final int DEFAULT_VIEWPORT_HEIGHT = 1080;
    public static final double DEFAULT_TOLERANCE = 0.01; // 1%
    public static final Path SCREENSHOTS_DIR = Paths.get("target/screenshots");
    public static final Path TRACES_DIR = Paths.get("target/traces");

    private Playwright playwright;
    private Browser browser;
    private final boolean headless;
    private final String baseUrl;
    private final int viewportWidth;
    private final int viewportHeight;

    public PlaywrightTestConfiguration() {
        this(
            System.getProperty("e2e.baseUrl", DEFAULT_BASE_URL),
            Boolean.parseBoolean(System.getProperty("playwright.headless", String.valueOf(DEFAULT_HEADLESS))),
            Integer.parseInt(System.getProperty("playwright.viewport.width", String.valueOf(DEFAULT_VIEWPORT_WIDTH))),
            Integer.parseInt(System.getProperty("playwright.viewport.height", String.valueOf(DEFAULT_VIEWPORT_HEIGHT)))
        );
    }

    public PlaywrightTestConfiguration(String baseUrl, boolean headless, int viewportWidth, int viewportHeight) {
        this.baseUrl = baseUrl;
        this.headless = headless;
        this.viewportWidth = viewportWidth;
        this.viewportHeight = viewportHeight;
    }

    /**
     * Initializes Playwright and launches the browser.
     * Must be called before creating pages.
     */
    public void initialize() {
        logger.info("Initializing Playwright");

        playwright = Playwright.create();
        browser = playwright.chromium().launch(
            new BrowserType.LaunchOptions()
                .setHeadless(headless)
                .setSlowMo(headless ? 0 : 100)
        );

        logger.info(() -> String.format(
            "Playwright initialized. Headless: %s, Base URL: %s, Viewport: %dx%d",
            headless, baseUrl, viewportWidth, viewportHeight
        ));
    }

    /**
     * Creates a new browser context with default settings.
     */
    public BrowserContext createContext() {
        return browser.newContext(new Browser.NewContextOptions()
            .setViewportSize(viewportWidth, viewportHeight)
        );
    }

    /**
     * Creates a new browser context with tracing enabled.
     */
    public BrowserContext createContextWithTracing(String traceName) {
        BrowserContext context = createContext();
        context.tracing().start(new com.microsoft.playwright.Tracing.StartOptions()
            .setScreenshots(true)
            .setSnapshots(true)
            .setSources(true)
        );
        return context;
    }

    /**
     * Stops tracing and saves it to a file.
     */
    public void stopTracing(BrowserContext context, String traceName) {
        context.tracing().stop(new com.microsoft.playwright.Tracing.StopOptions()
            .setPath(TRACES_DIR.resolve(traceName + ".zip"))
        );
    }

    /**
     * Creates a new page in a new context.
     */
    public Page createPage() {
        BrowserContext context = createContext();
        return context.newPage();
    }

    /**
     * Closes the browser and Playwright instance.
     */
    public void close() {
        if (browser != null) {
            browser.close();
        }
        if (playwright != null) {
            playwright.close();
        }
        logger.info("Playwright closed");
    }

    // Getters

    public String getBaseUrl() {
        return baseUrl;
    }

    public boolean isHeadless() {
        return headless;
    }

    public int getViewportWidth() {
        return viewportWidth;
    }

    public int getViewportHeight() {
        return viewportHeight;
    }

    public Browser getBrowser() {
        return browser;
    }

    public Playwright getPlaywright() {
        return playwright;
    }
}
