"""
GLAMWalk -- Volume 5: From Data to Product
07_d2d_compliance_checker.py

A real, general-purpose D2D/Kobo EPUB compliance checker: file size, valid ZIP/EPUB structure, no DRM, all four required metadata fields, and a real bug fix for parsing manifest tag attributes regardless of their order.

Source: Volume Five, Sections 5.1-5.2
Targets Python 3.11.4 -- see Volume One, Chapter 1.5/1.6.
"""

import zipfile
from pathlib import Path

def d2d_compliance_check(epub_path):
    """
    A real, general-purpose D2D/Kobo compliance checker — usable
    on ANY book's finished EPUB, not tied to one specific book type.
    Returns a list of (severity, message) tuples rather than a bare
    pass/fail, because a genuinely useful checker tells you exactly
    WHAT'S wrong, not just THAT something is.
    """
    issues = []
    path = Path(epub_path)

    if not path.exists():
        return [("fail", "File does not exist")]

    size_mb = path.stat().st_size / (1024 * 1024)
    if size_mb > 90:
        issues.append(("fail", f"File is {size_mb:.1f}MB — exceeds the 90MB hard limit"))
    elif size_mb > 70:
        issues.append(("warn", f"File is {size_mb:.1f}MB — approaching the size limit"))

    try:
        with zipfile.ZipFile(path) as zf:
            names = zf.namelist()

            if "mimetype" not in names:
                issues.append(("fail", "Missing required mimetype entry"))
            if not any(n.endswith(".opf") for n in names):
                issues.append(("fail", "Missing .opf package file"))
            if any("encryption.xml" in n for n in names):
                issues.append(("fail", "DRM/encryption.xml present — not allowed by any distributor"))

            opf_name = next((n for n in names if n.endswith(".opf")), None)
            if opf_name:
                opf_content = zf.read(opf_name).decode("utf-8", errors="replace")
                for field in ["dc:title", "dc:creator", "dc:language", "dc:identifier"]:
                    if f"<{field}" not in opf_content:
                        issues.append(("fail", f"Missing required metadata field: {field}"))

    except zipfile.BadZipFile:
        issues.append(("fail", "Not a valid ZIP/EPUB file"))

    if not issues:
        issues.append(("pass", "All checks passed"))

    return issues


import re

def parse_tag_attributes(tag_text):
    """
    Parse an XML/HTML tag's attributes into a dict, regardless of
    the order they appear in. A real, confirmed bug came from
    assuming a fixed order — different (correct, standards-compliant)
    tools write attributes in different orders.
    """
    attrs = {}
    for match in re.finditer(r'(\w[\w-]*)\s*=\s*"([^"]*)"', tag_text):
        attrs[match.group(1)] = match.group(2)
    return attrs
