import os
import base64
from jinja2 import Template

class VisualTestReport():
    """
    Genera el reporte html de las pruebas visuales hechas

    Ahora genera un HTML SINGLE (self-contained):
    - Embebe imágenes PNG en el HTML (data:image/png;base64,...)
    - No depende de rutas relativas (../) al abrir el reporte
    """

    # Directorio base de los screenshots
    base_dir = "ui"

    # Plantilla HTML para el reporte
    html_template = r"""
    <!DOCTYPE html>
    <html lang="es">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Visual Test Report</title>

    <style>
    body { font-family: Arial, sans-serif; margin: 20px; background: #fafafa; line-height: 1.6; }
    h1 { text-align: center; margin-bottom: 10px; }
    table { width: 100%; border-collapse: collapse; }
    th, td { border: 1px solid #ddd; padding: 10px; text-align: center; }
    th { background: #f4f4f4; }

    .summary { display: flex; justify-content: center; gap: 16px; margin: 10px 0 20px; flex-wrap: wrap; }
    .summary-item { padding: 6px 14px; border-radius: 6px; font-weight: bold; background: #eee; }
    .summary-item.failed { background: #fdecea; color: #b00020; }
    .summary-item.passed { background: #e8f5e9; color: #1b5e20; }

    .accordion { margin-bottom: 12px; }
    .accordion-header { display: flex; justify-content: space-between; padding: 12px; cursor: pointer; border-radius: 6px; border: 1px solid #ccc; font-weight: bold; align-items: center; }
    .accordion-header.success { background: #f1f8f4; border-left: 6px solid #2e7d32; color: #2e7d32; }
    .accordion-header.failed { background: #fdecea; border-left: 6px solid #c62828; color: #c62828; }
    .accordion-arrow { transition: transform 0.3s ease; }
    .accordion-header.active .accordion-arrow { transform: rotate(180deg); }
    .accordion-content { display: none; background: white; padding: 15px; border: 1px solid #ddd; border-top: none; }

    .image-wrapper { position: relative; }
    .image-label { position: absolute; top: 8px; left: 8px; background: rgba(0,0,0,0.6); color: white; font-size: 12px; padding: 4px 8px; border-radius: 4px; }
    img { max-width: 100%; height: auto; cursor: pointer; }

    .badge { display: inline-block; padding: 5px 12px; border-radius: 12px; font-size: 12px; font-weight: bold; }
    .badge.success { background: #e8f5e9; color: #1b5e20; }
    .badge.error { background: #fdecea; color: #b00020; }

    .error-box {
        margin-top: 10px;
        padding: 10px;
        border-radius: 6px;
        background: #fff5f5;
        border: 1px solid #ffd0d0;
        color: #7a0000;
        text-align: left;
        font-size: 13px;
        overflow-wrap: anywhere;
    }

    .lightbox { display: none; position: fixed; z-index: 999; inset: 0; background: rgba(0,0,0,0.85); }
    .lightbox img { margin: auto; display: block; max-width: 90%; max-height: 90%; transform-origin: center; }
    .close { position: absolute; top: 20px; right: 30px; color: white; font-size: 40px; cursor: pointer; }

    @media (max-width: 768px) { th, td { padding: 5px; } }
    </style>
    </head>

    <body>

    <h1>Visual Test Report</h1>

    <div class="summary">
        <span class="summary-item">Total: {{ total_test_failed + total_test_passed }}</span>
        <span class="summary-item failed">Fallidas: {{ total_test_failed }}</span>
        <span class="summary-item passed">Exitosas: {{ total_test_passed }}</span>
    </div>

    <!-- ==========================
         FAILED TESTS
    ========================== -->
    {% for folder, images in report_data_failed.items() %}
    <div class="accordion">
        <div class="accordion-header failed">
            {{ folder }}
            <span class="accordion-arrow">▼</span>
        </div>
        <div class="accordion-content">
            <table>
                <thead>
                    <tr>
                        <th>Esperaba</th>
                        <th>Obtuvo</th>
                        <th>Diff</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>
                            <div class="image-wrapper">
                                <span class="image-label">Esperado</span>
                                <img src="{{ images['ref_data'] }}" class="clickable-image">
                            </div>
                        </td>
                        <td>
                            <div class="image-wrapper">
                                <span class="image-label">Obtuvo</span>
                                <img src="{{ images['test_data'] }}" class="clickable-image">
                            </div>
                        </td>
                        <td>
                            <div class="image-wrapper">
                                <span class="image-label">Diff</span>
                                <img src="{{ images['diff_data'] }}" class="clickable-image">
                            </div>
                        </td>
                    </tr>
                </tbody>
            </table>

            <p class="badge error">❌ Prueba visual fallida </p>

            {% if images.get('error') %}
            <div class="error-box">
                <b>Detalle:</b><br>
                {{ images['error'] }}
            </div>
            {% endif %}
        </div>
    </div>
    {% endfor %}

    <!-- ==========================
         PASSED TESTS
    ========================== -->
    {% for folder, images in report_data_passed.items() %}
    <div class="accordion">
        <div class="accordion-header success">
            {{ folder }}
            <span class="accordion-arrow">▼</span>
        </div>
        <div class="accordion-content">
            <table>
                <thead>
                    <tr>
                        <th>Esperaba</th>
                        <th>Obtuvo</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>
                            <div class="image-wrapper">
                                <span class="image-label">Esperado</span>
                                <img src="{{ images['ref_data'] }}" class="clickable-image">
                            </div>
                        </td>
                        <td>
                            <div class="image-wrapper">
                                <span class="image-label">Obtuvo</span>
                                <img src="{{ images['test_data'] }}" class="clickable-image">
                            </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            <p class="badge success">✔ Prueba visual exitosa</p>
        </div>
    </div>
    {% endfor %}

    <!-- ==========================
         LIGHTBOX
    ========================== -->
    <div id="lightbox" class="lightbox">
        <span class="close">&times;</span>
        <img id="lightbox-img">
    </div>

    <script>
    const lightbox = document.getElementById("lightbox");
    const lightboxImg = document.getElementById("lightbox-img");
    const closeBtn = document.querySelector(".close");

    document.querySelectorAll(".clickable-image").forEach(img => {
        img.addEventListener("click", () => {
            lightbox.style.display = "block";
            lightboxImg.src = img.src;
            lightboxImg._scale = 1;
            lightboxImg.style.transform = "scale(1)";
        });
    });

    closeBtn.onclick = () => lightbox.style.display = "none";
    lightbox.onclick = e => { if (e.target === lightbox) lightbox.style.display = "none"; };

    lightboxImg.addEventListener("wheel", e => {
        e.preventDefault();
        const scale = e.deltaY < 0 ? 1.1 : 0.9;
        lightboxImg._scale *= scale;
        lightboxImg.style.transform = `scale(${lightboxImg._scale})`;
    });

    document.querySelectorAll(".accordion-header").forEach(header => {
        header.addEventListener("click", () => {
            document.querySelectorAll(".accordion-content").forEach(c => {
                if (c !== header.nextElementSibling) c.style.display = "none";
            });
            document.querySelectorAll(".accordion-header").forEach(h => h.classList.remove("active"));

            const content = header.nextElementSibling;
            content.style.display = content.style.display === "block" ? "none" : "block";
            header.classList.toggle("active");
        });
    });
    </script>

    </body>
    </html>
    """

    total_test_failed = 0
    total_test_passed = 0

    def _png_to_data_uri(self, path: str) -> str:
        with open(path, "rb") as f:
            b64 = base64.b64encode(f.read()).decode("utf-8")
        return f"data:image/png;base64,{b64}"

    # Función para buscar imágenes en carpetas con pruebas fallidas
    def collect_images_for_failed(self):
        report_data = {}
        for root, _, files in os.walk(self.base_dir):
            filtered_imgs = {file.split('.')[0]: os.path.join(root, file) for file in files if file.lower().endswith(".png")}
            if "ref" in filtered_imgs and "test" in filtered_imgs and "diff" in filtered_imgs:
                folder_name = os.path.basename(root)

                error_path = os.path.join(root, "error")
                if os.path.exists(error_path):
                    with open(error_path, 'r', encoding="utf-8", errors="ignore") as error_file:
                        error_text = error_file.read()
                else:
                    error_text = ''

                report_data[folder_name] = {
                    "ref_data": self._png_to_data_uri(filtered_imgs.get("ref")),
                    "test_data": self._png_to_data_uri(filtered_imgs.get("test")),
                    "diff_data": self._png_to_data_uri(filtered_imgs.get("diff")),
                    "error": error_text.replace('\n', '<br>')
                }
                self.total_test_failed = self.total_test_failed + 1
        return report_data

    # Función para buscar imágenes en carpetas con pruebas exitosas
    def collect_images_for_passed(self):
        report_data = {}
        for root, _, files in os.walk(self.base_dir):
            filtered_imgs = {file.split('.')[0]: os.path.join(root, file) for file in files if file.lower().endswith(".png")}
            if "ref" in filtered_imgs and "test" in filtered_imgs and not "diff" in filtered_imgs:
                folder_name = os.path.basename(root)
                report_data[folder_name] = {
                    "ref_data": self._png_to_data_uri(filtered_imgs.get("ref")),
                    "test_data": self._png_to_data_uri(filtered_imgs.get("test")),
                }
                self.total_test_passed = self.total_test_passed + 1
        return report_data

    # Generar el reporte
    def exec(self):
        output_file = "visual_test.html"
        report_data_failed = self.collect_images_for_failed()
        report_data_passed = self.collect_images_for_passed()
        html_template = Template(self.html_template)
        rendered_html = html_template.render(
            report_data_failed=report_data_failed,
            report_data_passed=report_data_passed,
            total_test_failed=self.total_test_failed,
            total_test_passed=self.total_test_passed
        )
        with open(output_file, "w", encoding="utf-8") as f:
            f.write(rendered_html)
        print(f"\nReporte del visual test generado")
        