#!/usr/bin/env python3
"""
Enhanced Anime Consistency Checker for Broken Spire
Generates detailed visual inconsistency reports
"""

import os
import sys
from pathlib import Path
from PIL import Image
import numpy as np

GENERATED_DIR = "/mnt/c/Users/fbmor/broken-spire-comparison/generated"
REFERENCES_DIR = "/mnt/c/Users/fbmor/broken-spire-comparison/references"

# Character profiles from reference images (detailed)
CHARACTER_PROFILES = {
    "Ash": {
        "reference": "Ash.png",
        "proportions": "Slim, athletic, dancer build, 1:6-7 head ratio",
        "face": "Young, androgynous, strong cheekbones, large expressive anime eyes",
        "hair": "Blond, medium length, messy, falls across forehead, wet look",
        "eyes": "Blue (exact shade varies by era)",
        "tattoos": "Black tribal pattern on arm and shoulder, sharp organic claw/flame style",
        "skin": "Pale",
        "clothing": "Variable by era - refugee youth, military, cemetery era",
        "accessories": "None in base reference",
        "palette": {"dominant": "blond", "secondary": "pale skin", "accent": "black tattoos"}
    },
    "Far-Future Ash": {
        "reference": "Far-Future Ash.png", 
        "proportions": "Mature, more muscular, imposing",
        "face": "Older, hardened, intense expression",
        "hair": "White/long white, flowing",
        "eyes": "Red glowing",
        "tattoos": "Expanded, more extensive, glowing red hexcore patterns",
        "clothing": "Dark armor",
        "accessories": "Multiple weapons, skull decorations",
        "palette": {"dominant": "white hair", "secondary": "dark armor", "accent": "red glow"}
    },
    "Everly": {
        "reference": "Everly.png",
        "proportions": "Fit, athletic, mid-30s",
        "face": "Sharp features, intense eyes, dark makeup",
        "hair": "Short dark hair",
        "eyes": "Intense, dark",
        "skin": "Light",
        "clothing": "Military uniform, tactical gear",
        "accessories": "Multiple weapons, scars visible",
        "palette": {"dominant": "dark/military colors", "secondary": "skin", "accent": "weapon metal"}
    },
    "Éva Moreau": {
        "reference": "Éva Moreau.png",
        "proportions": "Professional, average build",
        "face": "Blunt, intelligent, emotionally guarded",
        "hair": "Brown, shoulder length",
        "eyes": "Professional, focused",
        "skin": "Light",
        "clothing": "Lab coat, medical clothing",
        "accessories": "Surgical gloves, medical equipment",
        "palette": {"dominant": "white/medical", "secondary": "brown hair", "accent": "blue medical lights"}
    },
    "Nova": {
        "reference": "Nova Human.png",
        "proportions": "Young adult, fighter build",
        "face": "Playful, fierce, stylish",
        "hair": "Red, long flowing",
        "eyes": "Fierce, warm",
        "skin": "Light",
        "clothing": "Combat gear, stylish weapons",
        "accessories": "Multiple stylish weapons",
        "palette": {"dominant": "red hair", "secondary": "combat gear", "accent": "energy weapons"}
    },
    "Violet": {
        "reference": "Violet humaine.png",
        "proportions": "Elegant, dually human or devil form",
        "face": "Beautiful, soft in human form",
        "hair": "Purple, long",
        "eyes": "Red in devil form",
        "skin": "Light",
        "clothing": "Variable",
        "accessories": "Devil horns in devil form, dark wings",
        "palette": {"dominant": "purple", "secondary": "red", "accent": "crimson energy"}
    },
    "Lin Weishan": {
        "reference": "Lin Weishan.png",
        "proportions": "Fighter, athletic",
        "face": "Asian features, determined",
        "hair": "Black, long",
        "eyes": "Determined",
        "skin": "Light",
        "clothing": "Combat clothing, martial arts",
        "accessories": "Martial arts combat ready",
        "palette": {"dominant": "black hair", "secondary": "combat attire", "accent": "none"}
    },
    "TC-23": {
        "reference": "TC-23.png",
        "proportions": "Mechanical/augmented body",
        "face": "Cybernetic, esper powers",
        "hair": "Variable or bald",
        "eyes": "Glowing cybernetic",
        "skin": "Mechanical parts visible",
        "clothing": "Futuristic outfit",
        "accessories": "Robot parts, machinery",
        "palette": {"dominant": "metal/grey", "secondary": "glowing accents", "accent": "cybernetic blue"}
    },
    "Jonas": {
        "reference": "Jonas.png",
        "proportions": "Large, muscular, imposing",
        "face": "Scarred, warm smile despite harsh life",
        "hair": "Short brown",
        "eyes": "Warm, kind",
        "skin": "Weathered",
        "clothing": "Military/combat",
        "accessories": "Combat gear, scars",
        "palette": {"dominant": "brown", "secondary": "skin", "accent": "scar tissue"}
    }
}

def analyze_image_features(img_path):
    """Extract detailed visual features from an image"""
    try:
        img = Image.open(img_path).convert('RGB')
        img = img.resize((512, 512))
        arr = np.array(img)
        
        # Color analysis
        r, g, b = arr[:,:,0], arr[:,:,1], arr[:,:,2]
        
        # Dominant colors (simple k-means-like)
        avg_color = [r.mean(), g.mean(), b.mean()]
        
        # Brightness
        brightness = (r + g + b) / 3 / 255
        
        # Color temperature (warm vs cool)
        warmth = (r - b) / 255
        
        # Saturation
        max_rgb = np.maximum(np.maximum(r, g), b)
        min_rgb = np.minimum(np.minimum(r, g), b)
        saturation = (max_rgb - min_rgb) / 255
        
        # Edge detection (rough)
        gray = np.mean(arr, axis=2)
        edges = np.abs(gray[:,1:] - gray[:,:-1])
        edge_density = edges.mean()
        
        # Skin tone detection (rough heuristic)
        skin_mask = (r > 95) & (g > 40) & (b > 20) & (r > g) & (r > b) & ((r-g) + (r-b) > 15)
        skin_ratio = skin_mask.sum() / (512*512)
        
        return {
            "avg_color": avg_color,
            "brightness": float(brightness.mean()),
            "warmth": float(warmth.mean()),
            "saturation": float(saturation.mean()),
            "edge_density": float(edge_density),
            "skin_ratio": float(skin_ratio),
            "size": img.size
        }
    except Exception as e:
        print(f"Error analyzing {img_path}: {e}")
        return None

def compare_dimensions(gen_features, ref_profile):
    """Compare generated image against reference profile"""
    results = {}
    
    # Color palette check
    ref_palette = ref_profile.get("palette", {})
    if ref_palette.get("dominant"):
        # This is a simplified check - in reality would need image analysis
        results["color_palette"] = "⚠️ MANUAL CHECK REQUIRED"
    
    # Brightness (lighting)
    if gen_features:
        if gen_features["brightness"] < 0.3:
            results["lighting"] = "⚠️ Dark - may hide details"
        elif gen_features["brightness"] > 0.7:
            results["lighting"] = "⚠️ Bright - may lose contrast"
        else:
            results["lighting"] = "✅ Normal range"
    
    # Warmth
    if gen_features:
        if gen_features["warmth"] > 0.1:
            results["color_temperature"] = "⚠️ Warm shift"
        elif gen_features["warmth"] < -0.1:
            results["color_temperature"] = "⚠️ Cool shift"
        else:
            results["color_temperature"] = "✅ Neutral"
    
    # Skin ratio (for character images)
    if gen_features and gen_features.get("skin_ratio", 0) > 0.1:
        results["skin_visible"] = "✅ Character skin visible"
    elif gen_features:
        results["skin_visible"] = "⚠️ Limited skin visible"
    
    return results

def generate_detailed_report():
    """Generate comprehensive consistency report"""
    
    print("=" * 80)
    print("BROKEN SPIRE - ENHANCED ANIME CONSISTENCY CHECK")
    print("=" * 80)
    
    comparisons = [
        ("02_ash_birth_00002_.png", "Ash"),
        ("03_far_future_ash_evil_00002_.png", "Far-Future Ash"),
        ("05_everly_soldier_00002_.png", "Everly"),
        ("06_eva_doctor_00002_.png", "Éva Moreau"),
        ("07_nova_warrior_00002_.png", "Nova"),
        ("08_violet_devil_00002_.png", "Violet"),
        ("09_lin_weishan_00002_.png", "Lin Weishan"),
        ("10_tc23_esper_00002_.png", "TC-23"),
        ("11_jonas_ghost_00002_.png", "Jonas"),
    ]
    
    all_issues = []
    passed = 0
    failed = 0
    
    for filename, character in comparisons:
        print(f"\n{'='*80}")
        print(f"CHARACTER: {character}")
        print(f"{'='*80}")
        
        gen_path = os.path.join(GENERATED_DIR, filename)
        
        if not os.path.exists(gen_path):
            print(f"❌ GENERATED IMAGE MISSING: {filename}")
            failed += 1
            all_issues.append((character, "MISSING", filename))
            continue
        
        # Analyze generated image
        gen_features = analyze_image_features(gen_path)
        
        # Get reference profile
        ref_profile = CHARACTER_PROFILES.get(character, {})
        
        print(f"""
Reference     : {ref_profile.get('reference', 'N/A')}
Generated     : {filename}
Character     : {character}
""")
        
        print("-" * 80)
        print("DETAILED DIMENSIONAL ANALYSIS")
        print("-" * 80)
        
        # 1. PROPORTIONS
        print(f"""
1. PROPORTIONS
   Reference: {ref_profile.get('proportions', 'N/A')}
   Check:     Eye size relative to face, head-to-body ratio
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Compare head size to body in generated image
""")
        
        # 2. FACE & FEATURES
        print(f"""
2. FACE & FEATURES
   Reference: {ref_profile.get('face', 'N/A')}
   Eye Color: {ref_profile.get('eyes', 'N/A')}
   Check:     Eye shape, size, color matching; face shape
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Compare facial structure - nose, mouth, jawline
""")
        
        # 3. HAIR
        print(f"""
3. HAIR
   Reference: {ref_profile.get('hair', 'N/A')}
   Color:     {ref_profile.get('hair', 'N/A').split(',')[0] if ref_profile.get('hair') else 'N/A'}
   Check:     Hair color, length, style, bangs
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Look for parting direction, volume, distinctive features
""")
        
        # 4. CLOTHING
        print(f"""
4. CLOTHING
   Reference: {ref_profile.get('clothing', 'N/A')}
   Check:     Garment layers, colors, patterns, fit
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Check for correct layering and distinctive details
""")
        
        # 5. ACCESSORIES
        print(f"""
5. ACCESSORIES
   Reference: {ref_profile.get('accessories', 'N/A')}
   Check:     Position, color, material of all accessories
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Earrings, necklaces, headbands, etc.
""")
        
        # 6. COLOR PALETTE
        print(f"""
6. COLOR PALETTE
   Reference: {ref_profile.get('palette', {})}
   Generated: {gen_features['avg_color'] if gen_features else 'N/A'}
   Brightness: {gen_features['brightness'] if gen_features else 'N/A'}
   Warmth:    {gen_features['warmth'] if gen_features else 'N/A'}
   Status:    {'✅ ANALYSIS COMPLETE' if gen_features else '❌ NO DATA'}
   Notes:     Compare dominant colors between reference and generated
""")
        
        # 7. ART STYLE
        print(f"""
7. ART STYLE / SHADING
   Reference: Check line weight, shading method, detail level
   Generated: Edge density: {gen_features['edge_density'] if gen_features else 'N/A'}
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Compare cel-shading vs soft gradient, line quality
""")
        
        # 8. Tattoos/Markings (specific to Ash)
        if character == "Ash":
            print(f"""
8. TATTOOS / MARKINGS
   Reference: {ref_profile.get('tattoos', 'N/A')}
   Check:     Tribal pattern on arm/shoulder, claw/flame style
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Verify black tribal tattoos present and correct style
""")
        elif character == "Far-Future Ash":
            print(f"""
8. TATTOOS / MARKINGS
   Reference: {ref_profile.get('tattoos', 'N/A')}
   Check:     Expanded tattoos with red hexcore glow
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Verify expanded pattern with red glow effect
""")
        
        # 9. WEAPONS (if applicable)
        if ref_profile.get("weapons"):
            print(f"""
9. WEAPONS / ITEMS
   Reference: {ref_profile.get('weapons', 'N/A')}
   Check:     Type, size, color, grip position
   Status:    ⚠️ NEEDS MANUAL VERIFICATION
   Notes:     Compare weapon design to reference
""")
        
        # Visual analysis summary
        print("-" * 80)
        print("AUTOMATED ANALYSIS SUMMARY")
        print("-" * 80)
        
        if gen_features:
            print(f"""
   • Average Color (RGB): {gen_features['avg_color']}
   • Brightness: {gen_features['brightness']:.2f} ({'dark' if gen_features['brightness'] < 0.4 else 'normal' if gen_features['brightness'] < 0.7 else 'bright'})
   • Color Temperature: {'warm' if gen_features['warmth'] > 0.1 else 'cool' if gen_features['warmth'] < -0.1 else 'neutral'}
   • Saturation: {gen_features['saturation']:.2f} ({'muted' if gen_features['saturation'] < 0.3 else 'vivid'})
   • Edge Detail: {gen_features['edge_density']:.2f} ({'minimal' if gen_features['edge_density'] < 10 else 'detailed'})
   • Skin Visible: {gen_features['skin_ratio']*100:.1f}%
""")
        
        # CRITICAL ISSUES
        print("-" * 80)
        print("CRITICAL ISSUES CHECKLIST")
        print("-" * 80)
        
        issues = []
        
        # Hair color check
        if "blond" in ref_profile.get("hair", "").lower() and gen_features:
            # Check if brightness suggests blond-ish
            if gen_features['brightness'] > 0.5 and gen_features['warmth'] > 0:
                pass  # Likely okay
            else:
                issues.append("⚠️ Hair color may not match (check brightness/warmth)")
        
        # Check for skin visibility
        if gen_features and gen_features['skin_ratio'] < 0.05:
            issues.append("⚠️ Very limited skin visible - verify character presence")
        
        for issue in issues:
            print(f"  {issue}")
        
        if not issues:
            print("  ✅ No critical issues detected by automated analysis")
        
        all_issues.append((character, "REVIEW", filename))
        passed += 1
    
    # Final summary
    print("\n" + "=" * 80)
    print("FINAL SUMMARY")
    print("=" * 80)
    
    print(f"""
Total Characters Reviewed: {len(comparisons)}
Automated Pass: {passed}
Need Manual Review: {len(comparisons)}

DETAILED INCONSISTENCY REPORT:
=============================

The automated analysis can detect:
  ✓ Color palette distribution
  ✓ Brightness/lighting levels  
  ✓ Color temperature (warm/cool)
  ✓ Saturation levels
  ✓ Edge detail density
  ✓ Skin visibility ratio

The following CANNOT be detected automatically and require MANUAL REVIEW:
  ✗ Exact facial feature matching (eye shape, nose, mouth)
  ✗ Hair style exactness (bangs, parting)
  ✗ Clothing details and accessories
  ✗ Tattoo accuracy
  ✗ Art style (cel-shading vs soft)
  ✗ Proportion exactness

RECOMMENDED ACTIONS:
==================

1. For each character frame, manually compare:
   - Face shape and features vs reference
   - Hair color and style exactness
   - Clothing accuracy
   - Accessory presence and position

2. If any manual check fails, regenerate using IP-Adapter:
   - Open ComfyUI: https://mu1aafo3zo4da1-8188.proxy.runpod.net
   - Load reference image via IPAdapter Advanced
   - Use same prompt but with reference image
   - Replace generated frame

3. For batch review, use the anime-consistency-checker skill
   in the Kilo CLI with actual image files for detailed comparison
""")
    
    # Save report
    report_path = "/mnt/c/Users/fbmor/broken-spire-comparison/detailed_consistency_report.txt"
    with open(report_path, "w") as f:
        f.write("BROKEN SPIRE - DETAILED CONSISTENCY REPORT\n")
        f.write("=" * 60 + "\n\n")
        for char, status, file in all_issues:
            f.write(f"{char}: {status} ({file})\n")
        f.write("\n" + "=" * 60 + "\n")
        f.write("Full analysis above\n")
    
    print(f"\nReport saved to: {report_path}")

if __name__ == "__main__":
    generate_detailed_report()