import os
import re
import json
from pathlib import Path
from PIL import Image
import numpy as np

PRIMARY_SYNC_MAP = {
    "DRQ-20261001-CLI-LOADING-SCREEN-ART": "loading",
    "DRQ-20261001-CLI-LOGIN-PARALLAX-LAYERS": "banners",
    "DRQ-20261001-CLI-TOUCH-CONTROLS-PROMOTION": "ui/combat",
    "DRQ-20261001-CLI-WORLD-BACKGROUND-LAYERS": "map",
    "DRQ-20261001-ECO-BAZAAR-TRADE-PANELS": "ui/trade",
    "DRQ-20261001-ECO-CRAFTING-ORBS-CATALOG": "currencies",
    "DRQ-20261001-ECO-CURRENCY-BLOODSTONES": "currencies",
    "DRQ-20261001-ECO-LOOT-DROP-PARTICLES": "savage_vfx",
    "DRQ-20261001-NPC-CUTSCENE-STORYBOARD": "banners",
    "DRQ-20261001-NPC-FERAL-ELDERS-AVATARS": "characters/npcs",
    "DRQ-20261001-NPC-QUEST-SCROLL-VARIANTS": "ui/quests",
    "DRQ-20261001-SEC-ALERT-BADGES-QUARANTINE": "ui/security",
    "DRQ-20261001-SEC-SHIELD-ACTIVE-ANIMATION": "ui/security",
    "DRQ-20261001-SEC-UI-FORENSIC-WATERMARK": "ui/security",
    "DRQ-20261001-SRV-AGENT-ORB-ACTIVATION-VFX": "savage_vfx",
    "DRQ-20261001-SRV-AOI-SYNC-TELEMETRY-VISUAL": "ui",
    "DRQ-20261001-SRV-HARVEST-REPORT-OVERLAY": "ui",
    "DRQ-20261001-SYS-CRAFTING-STATION-UI": "ui",
    "DRQ-20261001-SYS-HIDEOUT-SAFEHAVEN-PROPS": "map",
    "DRQ-20261001-SYS-MAP-DEVICE-ARENA": "map",
    "DRQ-20261001-SYS-PASSIVE-TREE-NODES": "ui/passive_tree",
}

def is_power_of_two(n):
    return n > 0 and (n & (n - 1)) == 0

approved_md_dir = Path("docs/design_requests/approved")
approved_assets_dir = Path("assets/approved")
client_assets_dir = Path("client/webapp/assets")

drq_files = sorted([f for f in approved_md_dir.glob("DRQ-20261001-*.md")])
print(f"Auditing {len(drq_files)} DRQ asset packages...")

errors = []
total_deliverables = 0
image_pot_verified = 0
normal_map_verified = 0
json_verified = 0
metal_verified = 0

for drq_path in drq_files:
    req_id = drq_path.stem
    content = drq_path.read_text(encoding="utf-8")
    
    # Extract deliverables from section 4
    delivs = re.findall(r"- \[[xX]\]\s*`([^`\n]+)`", content)
    if not delivs:
        errors.append(f"[{req_id}] No deliverables found in Section 4!")
        continue
    
    dest_subfolder = PRIMARY_SYNC_MAP.get(req_id)
    if not dest_subfolder:
        errors.append(f"[{req_id}] Missing mapping in PRIMARY_SYNC_MAP!")
        continue
    
    for filename in delivs:
        total_deliverables += 1
        
        # 1. Check in assets/approved/<req_id>/
        appr_file = approved_assets_dir / req_id / filename
        if not appr_file.exists():
            errors.append(f"[{req_id}] Missing approved asset: {appr_file}")
            continue
        if appr_file.stat().st_size == 0:
            errors.append(f"[{req_id}] Empty approved asset: {appr_file}")
            continue
            
        # 2. Check in client/webapp/assets/<dest_subfolder>/
        client_file = client_assets_dir / dest_subfolder / filename
        if not client_file.exists():
            errors.append(f"[{req_id}] Missing client asset: {client_file}")
            continue
        if client_file.stat().st_size == 0:
            errors.append(f"[{req_id}] Empty client asset: {client_file}")
            continue
            
        # 3. Content specific checks
        ext = client_file.suffix.lower()
        if ext in [".png", ".jpg", ".jpeg", ".webp"]:
            try:
                with Image.open(client_file) as img:
                    w, h = img.size
                    if not (is_power_of_two(w) and is_power_of_two(h)):
                        errors.append(f"[{req_id}] {filename} ({w}x{h}) is NOT power of 2!")
                    else:
                        image_pot_verified += 1
                        
                    if "normal" in filename.lower():
                        arr = np.array(img.convert("RGBA"))
                        # Blue channel is index 2
                        b_mean = np.mean(arr[:, :, 2])
                        if b_mean < 128.0:
                            errors.append(f"[{req_id}] {filename} normal map Blue mean ({b_mean:.2f}) < 128!")
                        else:
                            normal_map_verified += 1
            except Exception as e:
                errors.append(f"[{req_id}] Corrupt image {filename}: {e}")
                
        elif ext == ".json":
            try:
                with open(client_file, "r", encoding="utf-8") as jf:
                    data = json.load(jf)
                json_verified += 1
            except Exception as e:
                errors.append(f"[{req_id}] Invalid JSON in {filename}: {e}")
                
        elif ext == ".metal":
            text = client_file.read_text(encoding="utf-8")
            if "kernel" not in text and "vertex" not in text and "fragment" not in text:
                errors.append(f"[{req_id}] Metal shader {filename} missing entry points!")
            else:
                metal_verified += 1

print("\n--- AUDIT SUMMARY ---")
print(f"Total DRQs: {len(drq_files)}")
print(f"Total Deliverables verified: {total_deliverables}")
print(f"Power-of-Two Images verified: {image_pot_verified}")
print(f"Normal Maps verified (B-mean >= 128): {normal_map_verified}")
print(f"JSON Metadata files verified: {json_verified}")
print(f"Apple Metal Shaders verified: {metal_verified}")

if errors:
    print(f"\n[FAIL] Found {len(errors)} errors:")
    for err in errors:
        print("  - " + err)
else:
    print("\n[PASS] All deliverables exist, are non-empty, and strictly pass all quality gates!")
