#!/usr/bin/env python3
"""Static pre-render checks for HyperFrames HTML compositions."""

from __future__ import annotations

import argparse
import re
import sys
from pathlib import Path


def has_attr(html: str, name: str) -> bool:
    return re.search(rf"\b{name}\s*=\s*['\"]?[^'\"\s>]+", html, re.IGNORECASE) is not None


def check_html(html: str, *, component: bool = False) -> tuple[list[str], list[str]]:
    failures: list[str] = []
    warnings: list[str] = []

    if not component:
        for attr in ("data-width", "data-height", "data-duration", "data-composition-id"):
            if not has_attr(html, attr):
                failures.append(f"missing {attr}")

    if "<!-- paste from " in html:
        failures.append("unresolved component paste placeholder")

    paused_timeline = re.search(
        r"gsap\s*\.\s*timeline\s*\(\s*\{[^}]*paused\s*:\s*true",
        html,
        re.IGNORECASE | re.DOTALL,
    )
    if not paused_timeline:
        failures.append("missing gsap.timeline({ paused: true })")

    if "window.__timelines" not in html:
        failures.append("missing window.__timelines registration")

    if re.search(r"\bDate\s*\.\s*now\s*\(", html):
        failures.append("uses Date.now(); render progress must be timeline-driven")

    if re.search(r"\bsetInterval\s*\(", html):
        failures.append("uses setInterval(); primary render progress must be timeline-driven")

    if re.search(r"\brequestAnimationFrame\s*\(", html) and "fallback" not in html.lower():
        warnings.append("requestAnimationFrame found; ensure it is not the primary render clock and has render fallback")

    if "<style" in html.lower() and "[data-composition-id" not in html:
        warnings.append("style block found without [data-composition-id] scoped selector")

    if len(re.findall(r"data-duration\s*=\s*['\"]?(\d+(?:\.\d+)?)", html)) > 1:
        warnings.append("multiple data-duration values found; verify the intended render duration")

    return failures, warnings


def main() -> int:
    parser = argparse.ArgumentParser(description="Validate HyperFrames HTML before render.")
    parser.add_argument("html_file", help="Path to a HyperFrames HTML file")
    parser.add_argument(
        "--component",
        action="store_true",
        help="Validate a component snippet instead of a full block composition",
    )
    args = parser.parse_args()

    path = Path(args.html_file)
    if not path.exists():
        print(f"FAIL: file does not exist: {path}", file=sys.stderr)
        return 2

    html = path.read_text(encoding="utf-8")
    failures, warnings = check_html(html, component=args.component)

    for warning in warnings:
        print(f"WARN: {warning}", file=sys.stderr)

    if failures:
        for failure in failures:
            print(f"FAIL: {failure}", file=sys.stderr)
        return 1

    print("OK: HyperFrames HTML passed static pre-render checks")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
