package com.agile611.testng.webdriver;

import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import net.lightbody.bmp.core.har.Har;
import net.lightbody.bmp.core.har.HarEntry;
import net.lightbody.bmp.core.har.HarNameValuePair;
import net.lightbody.bmp.core.har.HarRequest;
import net.lightbody.bmp.core.har.HarResponse;

import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import java.io.File;
import java.util.List;

public class MarcaHARTest {
    WebDriver driver;
    BrowserMobProxy proxy;

    @BeforeMethod
    public void setUp() throws Exception {
        // 1. Iniciar el servidor Proxy localmente
        proxy = new BrowserMobProxyServer();
        proxy.start(0); // El puerto 0 le dice que busque cualquier puerto libre

        // 2. Crear el objeto Proxy de Selenium a partir del BrowserMob
        Proxy seleniumProxy = ClientUtil.createSeleniumProxy(proxy);

        // 3. Inyectar el proxy en las opciones de Firefox
        FirefoxOptions options = new FirefoxOptions();
        options.setProxy(seleniumProxy);
        
        // Nota: Si usas Selenium 4.6+, esta línea ya no es necesaria gracias a Selenium Manager
        System.setProperty("webdriver.gecko.driver",
                "src" + File.separator + "test"
                        + File.separator + "resources"
                        + File.separator + "geckodriver-macos");
                        
        driver = new FirefoxDriver(options);
    }

    @AfterMethod
    public void tearDown() {
        // Es crucial apagar ambos servicios para no dejar procesos huérfanos
        if (driver != null) {
            driver.quit();
        }
        if (proxy != null) {
            proxy.stop();
        }
    }

    @Test
    public void allImagesLoaded() throws InterruptedException {
        // 4. Iniciar la captura de un nuevo archivo HAR
        proxy.newHar("captura_imagenes");

        // 5. Navegar a la página (el proxy registrará todo el tráfico)
        driver.navigate().to("http://www.marca.com");

        // 6. Extraer el HAR generado
        Har har = proxy.getHar();

        // 7. Analizar las entradas de red
        List<HarEntry> entries = har.getLog().getEntries();
        Thread.sleep(15000);

        for (HarEntry entry : entries) {
            HarRequest request = entry.getRequest();
            HarResponse response = entry.getResponse();

            System.out.println("==================================================");
            System.out.println("🌐 URL: " + request.getUrl());
            System.out.println("▶️ Método HTTP: " + request.getMethod());
            System.out.println("◀️ Código de Estado: " + response.getStatus() + " " + response.getStatusText());
            System.out.println("⏱️ Tiempo Total: " + entry.getTime() + " ms");

            // 1. Extraer Cabeceras de la Petición (Request Headers)
            System.out.println("\n📦 CABECERAS DE PETICIÓN:");
            for (HarNameValuePair header : request.getHeaders()) {
                System.out.println("   - " + header.getName() + ": " + header.getValue());
            }

            // 2. Extraer Cabeceras de la Respuesta (Response Headers)
            System.out.println("\n📥 CABECERAS DE RESPUESTA:");
            for (HarNameValuePair header : response.getHeaders()) {
                System.out.println("   - " + header.getName() + ": " + header.getValue());
            }

            // 3. Extraer Información del Contenido
            System.out.println("\n📄 DETALLES DEL CONTENIDO:");
            System.out.println("   - Tipo MIME: " + response.getContent().getMimeType());
            System.out.println("   - Tamaño del cuerpo: " + response.getContent().getSize() + " bytes");
            
            // Opcional: Imprimir el texto de la respuesta (Cuidado, puede ser muy largo para HTML/JS)
            // if (response.getContent().getText() != null) {
            //     System.out.println("   - Contenido: " + response.getContent().getText().substring(0, Math.min(response.getContent().getText().length(), 100)) + "...");
            // }

            // 4. Extraer Tiempos de Red (Timings)
            System.out.println("\n⏳ DESGLOSE DE TIEMPOS:");
            System.out.println("   - Bloqueado (Blocked): " + entry.getTimings().getBlocked() + " ms");
            System.out.println("   - Resolución DNS: " + entry.getTimings().getDns() + " ms");
            System.out.println("   - Conexión: " + entry.getTimings().getConnect() + " ms");
            System.out.println("   - Espera al servidor (TTFB): " + entry.getTimings().getWait() + " ms");
            System.out.println("   - Descarga de datos (Receive): " + entry.getTimings().getReceive() + " ms");
            System.out.println("==================================================\n");
        }
    }
}