import os
import sys
from PIL import Image, ImageStat

sys.stdout.reconfigure(encoding='utf-8')

styles_root = "client/webapp/assets/map/styles"
PNG_MAGIC = b"\x89PNG\r\n\x1a\n"

REQUIRED_ASSET_FILES = (
    "floor.png",
    "wall.png",
    "path.png",
    "liquid.png",
    "props.png",
    "floor_normal.png",
    "wall_normal.png",
    "path_normal.png",
    "liquid_normal.png",
)

NORMAL_MAP_FILES = (
    "floor_normal.png",
    "wall_normal.png",
    "path_normal.png",
    "liquid_normal.png",
)

VALID_TILE_DIMS = {(64, 32), (128, 64)}
VALID_WALL_DIMS = {(128, 128)}

style_dirs = sorted([d for d in os.listdir(styles_root) if os.path.isdir(os.path.join(styles_root, d)) and d.startswith("sty_")])
print(f"Total style directories: {len(style_dirs)}")

errors = []
blue_means = []
file_count = 0
total_size = 0

for s_dir in style_dirs:
    dir_path = os.path.join(styles_root, s_dir)
    
    # 1. Check the 9 core files
    for req in REQUIRED_ASSET_FILES:
        f_path = os.path.join(dir_path, req)
        if not os.path.exists(f_path):
            errors.append(f"MISSING: {f_path}")
            continue
        
        file_count += 1
        f_size = os.path.getsize(f_path)
        total_size += f_size
        
        # Check size cap (60 KB)
        if f_size > 60 * 1024:
            errors.append(f"OVERSIZED: {f_path} ({f_size} bytes > 60KB)")
        
        # Check PNG magic
        with open(f_path, "rb") as f:
            magic = f.read(8)
            if magic != PNG_MAGIC:
                errors.append(f"CORRUPT MAGIC: {f_path}")

        # Check dimensions & image load
        try:
            with Image.open(f_path) as img:
                w, h = img.size
                if req in ("floor.png", "path.png", "liquid.png", "floor_normal.png", "path_normal.png", "liquid_normal.png"):
                    if (w, h) not in VALID_TILE_DIMS:
                        errors.append(f"INVALID DIMS: {f_path} -> {(w, h)} not in {VALID_TILE_DIMS}")
                elif req in ("wall.png", "wall_normal.png"):
                    if (w, h) not in VALID_WALL_DIMS:
                        errors.append(f"INVALID WALL DIMS: {f_path} -> {(w, h)} not in {VALID_WALL_DIMS}")
                
                # Check normal maps
                if req in NORMAL_MAP_FILES:
                    stat = ImageStat.Stat(img)
                    if len(stat.mean) >= 3:
                        b_mean = float(stat.mean[2])
                        blue_means.append(b_mean)
                        if b_mean <= 128.0:
                            errors.append(f"LOW BLUE NORMAL: {f_path} -> blue mean {b_mean:.2f} <= 128.0")
                    else:
                        errors.append(f"NON-RGB NORMAL: {f_path} (channels < 3)")
        except Exception as e:
            errors.append(f"IMG OPEN ERROR: {f_path} -> {e}")

    # 2. Check props subdirectory
    props_sub = os.path.join(dir_path, "props")
    if not os.path.exists(props_sub) or not os.path.isdir(props_sub):
        errors.append(f"MISSING PROPS DIR: {props_sub}")
    else:
        props_files = [f for f in os.listdir(props_sub) if f.endswith(".png")]
        if len(props_files) != 3:
            errors.append(f"UNEXPECTED PROPS COUNT: {props_sub} has {len(props_files)} pngs (expected 3)")
        for pf in props_files:
            file_count += 1
            pf_path = os.path.join(props_sub, pf)
            f_size = os.path.getsize(pf_path)
            total_size += f_size
            with open(pf_path, "rb") as f:
                magic = f.read(8)
                if magic != PNG_MAGIC:
                    errors.append(f"CORRUPT PROP MAGIC: {pf_path}")

print(f"\n--- AUDIT RESULTS ---")
print(f"Total styles checked: {len(style_dirs)}")
print(f"Total PNG files verified: {file_count} (30 styles * 9 core + 30 styles * 3 props = 360 files)")
print(f"Total asset size: {total_size / (1024*1024):.2f} MB (budget < 10 MB)")
print(f"Total normal maps checked: {len(blue_means)} (30 styles * 4 normal maps = 120)")
if blue_means:
    print(f"Blue channel stats: min={min(blue_means):.2f}, max={max(blue_means):.2f}, avg={sum(blue_means)/len(blue_means):.2f}")
print(f"Total errors/violations: {len(errors)}")
if errors:
    for err in errors[:20]:
        print(f"  [ERROR] {err}")
    sys.exit(1)
else:
    print("[ALL PASS] 100% of 30 styles contain complete valid PNG textures and normal maps with Blue mean > 128.0!")
