"""Local fixture tests. All browser HTTP requests are intercepted; no site is read.

Run separately: py test_browser_pdf.py --output <new-test-directory>
Requires installed Chromium and the normal requirements.
"""
import argparse
import copy
import json
from pathlib import Path

from playwright.sync_api import sync_playwright
from pypdf import PdfReader

import heilind_sku_pdf as tool
from test_heilind_sku_pdf import candidate, fake_manifest


def fixture(sku):
    rows = "".join(f"<tr><td>TEST ATTRIBUTE {i:03d}</td><td>Fixture value {i} - test data only</td></tr>"
                   for i in range(1, 91))
    return f'''<!doctype html><html><head><meta charset="utf-8"><title>LOCAL TEST FIXTURE {sku}</title>
    <style>body{{margin:0;font:17px/1.5 Arial;color:#19344b}}header,footer{{background:#19344b;color:#fff;padding:40px}}
    main{{padding:40px;max-width:1300px;margin:auto}}h1{{font-size:38px}}table{{width:100%;border-collapse:collapse}}
    td,th{{padding:12px;border-bottom:1px solid #ddd}}th{{text-align:left;background:#edf5fa}}tr:nth-child(even){{background:#f7f9fb}}
    .banner{{background:#fff1cb;padding:24px;margin-bottom:24px}}details{{padding:20px;border:1px solid #ddd;margin:30px 0}}</style>
    </head><body><header>LOCAL TEST FIXTURE - NOT A LIVE HEILIND PAGE</header><main><h1>{sku}</h1>
    <div class="banner">Synthetic content solely for browser/PDF validation. This is not product data.</div>
    <p>Test fixture manufacturer. This text ensures the product page has enough rendered content for the capture validation checks.</p>
    <table><thead><tr><th>Attribute</th><th>Value</th></tr></thead><tbody>{rows}</tbody></table>
    <details><summary>Additional test content</summary><p>NATIVE DETAILS CONTENT INCLUDED</p></details></main>
    <footer>END OF PRODUCT TEST FOOTER</footer></body></html>'''


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()
    out = args.output.resolve()
    out.mkdir(parents=True, exist_ok=False)
    (out / "product_pdfs").mkdir()
    settings = copy.deepcopy(tool.DEFAULTS["capture"])
    settings.update(settle_seconds=0, between_pages_seconds=0)
    manifest = fake_manifest()
    rows = []
    for i in range(25):
        row = candidate(f"TESTSKU{i:02d}", f"TEST MFG {i % 12:02d}", 4, 12 + i % 7)
        row.update(percent_increase=(row["conversion_count"] - 4) / 4 * 100,
                   url=tool.product_url(row["sku"], settings), capture_status="pending")
        rows.append(row)
    manifest["selected"] = rows
    manifest["warnings"].append("LOCAL TEST FIXTURE ONLY - not live product or database evidence.")
    with sync_playwright() as p:
        browser = p.chromium.launch()
        context = browser.new_context(viewport={"width": 1440, "height": 1000})

        def route(request):
            if "blocked" in request.request.url:
                request.fulfill(status=403, content_type="text/html", body="<h1>Access denied</h1>")
            elif "missing" in request.request.url:
                request.fulfill(status=200, content_type="text/html", body="<h1>404 Not Found</h1>")
            else:
                request.fulfill(status=200, content_type="text/html", body=fixture("TESTSKU00"))

        context.route("**/*", route)
        tool.capture_one(context, rows[0], 1, out, settings)
        assert rows[0]["capture_status"] == "saved", rows[0]
        pdf = PdfReader(str(out / rows[0]["pdf_file"]))
        assert len(pdf.pages) == 1, "Continuous output should be a single tall page"
        assert float(pdf.pages[0].mediabox.height) > 3000, "PDF is only viewport-sized"
        contents = "\n".join(page.extract_text() for page in pdf.pages)
        for marker in ("TEST ATTRIBUTE 090", "NATIVE DETAILS CONTENT INCLUDED", "END OF PRODUCT TEST FOOTER"):
            assert marker in contents, f"Missing full-page content: {marker}"

        # The single-page size guard must fall back to complete paginated output.
        page = context.new_page()
        page.set_content(fixture("TESTSKU00"))
        tool.prepare_page(page, settings)
        paged_settings = {**settings, "max_single_page_height_px": 1000}
        layout = tool.print_full_page(page, out / "fixture_paged.pdf", paged_settings)
        assert layout == "paged"
        paged = PdfReader(str(out / "fixture_paged.pdf"))
        assert len(paged.pages) >= 3
        assert "END OF PRODUCT TEST FOOTER" in "\n".join(p.extract_text() for p in paged.pages)
        page.close()

        for kind, expected in (("blocked", tool.CaptureBlocked), ("missing", RuntimeError)):
            bad = candidate(kind, "TEST")
            bad["url"] = f"https://fixture.invalid/{kind}.html"
            try:
                tool.capture_one(context, bad, 99, out, settings)
                raise AssertionError(f"{kind} page incorrectly saved")
            except expected:
                pass
            assert "pdf_file" not in bad
        tool.checkpoint(out, manifest)
        # Only a local file navigation may bypass the route's synthetic HTTP response.
        context.unroute("**/*", route)
        context.route("http://**/*", lambda route: route.abort())
        context.route("https://**/*", lambda route: route.abort())
        tool.export_summary(context, out)
        context.close()
        browser.close()
    summary = PdfReader(str(out / "selection_summary.pdf"))
    summary_text = "\n".join(p.extract_text() for p in summary.pages)
    assert all(row["sku"] in summary_text for row in rows)
    tool.combine_pdfs(out, manifest)
    combined = PdfReader(str(out / "all_selected_product_pages.pdf"))
    assert len(combined.pages) == len(summary.pages) + 1
    print(json.dumps({"result": "PASS", "fixture": "synthetic, all HTTP requests intercepted",
                      "continuous_pdf_pages": len(pdf.pages), "continuous_height_points": float(pdf.pages[0].mediabox.height),
                      "paged_pdf_pages": len(paged.pages), "summary_pages": len(summary.pages),
                      "all_25_summary_skus_present": True, "end_of_page_present": True,
                      "blocked_and_soft_404_rejected": True, "output": str(out)}, indent=2))


if __name__ == "__main__":
    main()
