#!/usr/bin/env python3
"""Debug pose classification for identified faces

This script helps identify why poses might be incorrectly classified.
It shows detailed pose information and can recalculate poses from photos.
"""

import sys
import os
import json
from typing import Optional, List, Tuple

# Add project root to path
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from backend.db.models import Face, Person, Photo
from backend.db.session import get_database_url
from src.utils.pose_detection import PoseDetector


def analyze_pose_classification(
    face_id: Optional[int] = None,
    person_id: Optional[int] = None,
    recalculate: bool = False,
) -> None:
    """Analyze pose classification for identified faces.
    
    Args:
        face_id: Specific face ID to check (None = all identified faces)
        person_id: Specific person ID to check (None = all persons)
        recalculate: If True, recalculate pose from photo to verify classification
    """
    db_url = get_database_url()
    print(f"Connecting to database: {db_url}")
    
    engine = create_engine(db_url)
    Session = sessionmaker(bind=engine)
    session = Session()
    
    try:
        # Build query
        query = (
            session.query(Face, Person, Photo)
            .join(Person, Face.person_id == Person.id)
            .join(Photo, Face.photo_id == Photo.id)
            .filter(Face.person_id.isnot(None))
        )
        
        if face_id:
            query = query.filter(Face.id == face_id)
        if person_id:
            query = query.filter(Person.id == person_id)
        
        faces = query.order_by(Person.id, Face.id).all()
        
        if not faces:
            print("No identified faces found matching criteria.")
            return
        
        print(f"\n{'='*80}")
        print(f"Found {len(faces)} identified face(s)")
        print(f"{'='*80}\n")
        
        pose_detector = None
        if recalculate:
            try:
                pose_detector = PoseDetector()
                print("Pose detector initialized for recalculation\n")
            except Exception as e:
                print(f"Warning: Could not initialize pose detector: {e}")
                print("Skipping recalculation\n")
                recalculate = False
        
        for face, person, photo in faces:
            person_name = f"{person.first_name} {person.last_name}"
            
            print(f"{'='*80}")
            print(f"Face ID: {face.id}")
            print(f"Person: {person_name} (ID: {person.id})")
            print(f"Photo: {photo.filename}")
            print(f"Photo Path: {photo.path}")
            print(f"{'-'*80}")
            
            # Current stored pose information
            print("STORED POSE INFORMATION:")
            print(f"  Pose Mode: {face.pose_mode}")
            print(f"  Yaw Angle: {face.yaw_angle:.2f}°" if face.yaw_angle is not None else "  Yaw Angle: None")
            print(f"  Pitch Angle: {face.pitch_angle:.2f}°" if face.pitch_angle is not None else "  Pitch Angle: None")
            print(f"  Roll Angle: {face.roll_angle:.2f}°" if face.roll_angle is not None else "  Roll Angle: None")
            print(f"  Face Confidence: {face.face_confidence:.3f}")
            print(f"  Quality Score: {face.quality_score:.3f}")
            
            # Parse location
            try:
                location = json.loads(face.location) if isinstance(face.location, str) else face.location
                print(f"  Location: {location}")
            except:
                print(f"  Location: {face.location}")
            
            # Analyze classification
            print(f"\nPOSE CLASSIFICATION ANALYSIS:")
            yaw = face.yaw_angle
            pitch = face.pitch_angle
            roll = face.roll_angle
            
            if yaw is not None:
                abs_yaw = abs(yaw)
                print(f"  Yaw: {yaw:.2f}° (absolute: {abs_yaw:.2f}°)")
                
                if abs_yaw < 30.0:
                    expected_mode = "frontal"
                    print(f"  → Expected: {expected_mode} (yaw < 30°)")
                elif yaw <= -30.0:
                    expected_mode = "profile_left"
                    print(f"  → Expected: {expected_mode} (yaw <= -30°, face turned left)")
                elif yaw >= 30.0:
                    expected_mode = "profile_right"
                    print(f"  → Expected: {expected_mode} (yaw >= 30°, face turned right)")
                else:
                    expected_mode = "unknown"
                    print(f"  → Expected: {expected_mode} (edge case)")
                
                if face.pose_mode != expected_mode:
                    print(f"  ⚠️  MISMATCH: Stored pose_mode='{face.pose_mode}' but expected '{expected_mode}'")
                else:
                    print(f"  ✓ Classification matches expected mode")
            else:
                print(f"  Yaw: None (cannot determine pose from yaw)")
                print(f"  ⚠️  Warning: Yaw angle is missing, pose classification may be unreliable")
            
            # Recalculate if requested
            if recalculate and pose_detector and photo.path and os.path.exists(photo.path):
                print(f"\nRECALCULATING POSE FROM PHOTO:")
                try:
                    pose_faces = pose_detector.detect_pose_faces(photo.path)
                    
                    if not pose_faces:
                        print("  No faces detected in photo")
                    else:
                        # Try to match face by location
                        face_location = location if isinstance(location, dict) else json.loads(face.location) if isinstance(face.location, str) else {}
                        face_x = face_location.get('x', 0)
                        face_y = face_location.get('y', 0)
                        face_w = face_location.get('w', 0)
                        face_h = face_location.get('h', 0)
                        face_center_x = face_x + face_w / 2
                        face_center_y = face_y + face_h / 2
                        
                        best_match = None
                        best_distance = float('inf')
                        
                        for pose_face in pose_faces:
                            pose_area = pose_face.get('facial_area', {})
                            if isinstance(pose_area, dict):
                                pose_x = pose_area.get('x', 0)
                                pose_y = pose_area.get('y', 0)
                                pose_w = pose_area.get('w', 0)
                                pose_h = pose_area.get('h', 0)
                                pose_center_x = pose_x + pose_w / 2
                                pose_center_y = pose_y + pose_h / 2
                                
                                # Calculate distance between centers
                                distance = ((face_center_x - pose_center_x) ** 2 + 
                                           (face_center_y - pose_center_y) ** 2) ** 0.5
                                
                                if distance < best_distance:
                                    best_distance = distance
                                    best_match = pose_face
                        
                        if best_match:
                            recalc_yaw = best_match.get('yaw_angle')
                            recalc_pitch = best_match.get('pitch_angle')
                            recalc_roll = best_match.get('roll_angle')
                            recalc_face_width = best_match.get('face_width')
                            recalc_pose_mode = best_match.get('pose_mode')
                            
                            print(f"  Recalculated Yaw: {recalc_yaw:.2f}°" if recalc_yaw is not None else "  Recalculated Yaw: None")
                            print(f"  Recalculated Pitch: {recalc_pitch:.2f}°" if recalc_pitch is not None else "  Recalculated Pitch: None")
                            print(f"  Recalculated Roll: {recalc_roll:.2f}°" if recalc_roll is not None else "  Recalculated Roll: None")
                            print(f"  Face Width: {recalc_face_width:.2f}px" if recalc_face_width is not None else "  Face Width: None")
                            print(f"  Recalculated Pose Mode: {recalc_pose_mode}")
                            
                            # Compare
                            if recalc_pose_mode != face.pose_mode:
                                print(f"  ⚠️  MISMATCH: Stored='{face.pose_mode}' vs Recalculated='{recalc_pose_mode}'")
                            
                            if recalc_yaw is not None and face.yaw_angle is not None:
                                # Convert Decimal to float for comparison
                                stored_yaw = float(face.yaw_angle)
                                yaw_diff = abs(recalc_yaw - stored_yaw)
                                if yaw_diff > 1.0:  # More than 1 degree difference
                                    print(f"  ⚠️  Yaw difference: {yaw_diff:.2f}°")
                        else:
                            print("  Could not match face location to detected faces")
                            
                except Exception as e:
                    print(f"  Error recalculating: {e}")
                    import traceback
                    traceback.print_exc()
            
            print()
        
        print(f"{'='*80}")
        print("Analysis complete")
        print(f"{'='*80}\n")
    
    finally:
        session.close()


def main():
    """Main entry point"""
    import argparse
    
    parser = argparse.ArgumentParser(
        description="Debug pose classification for identified faces"
    )
    parser.add_argument(
        "--face-id",
        type=int,
        help="Specific face ID to check"
    )
    parser.add_argument(
        "--person-id",
        type=int,
        help="Specific person ID to check"
    )
    parser.add_argument(
        "--recalculate",
        action="store_true",
        help="Recalculate pose from photo to verify classification"
    )
    
    args = parser.parse_args()
    
    try:
        analyze_pose_classification(
            face_id=args.face_id,
            person_id=args.person_id,
            recalculate=args.recalculate,
        )
    except Exception as e:
        print(f"❌ Error: {e}")
        import traceback
        traceback.print_exc()
        sys.exit(1)


if __name__ == "__main__":
    main()

