"""
test_face_camera.py — Live camera face match test
Usage: python test_face_camera.py

Shows live camera feed. Press SPACE to capture and test against Rekognition.
Press Q to quit.

Install requirements first:
  pip install opencv-python mysql-connector-python
"""
import sys
import io
import cv2
import mysql.connector
from config.aws_config import get_aws_settings, get_rekognition_client

# ── DB config ─────────────────────────────────────────────────────
DB_CONFIG = {
    "host":     "127.0.0.1",
    "user":     "root",
    "password": "",          # your DB password
    "database": "event_ai"
}

def get_user_by_face_id(face_id):
    try:
        conn   = mysql.connector.connect(**DB_CONFIG)
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT id, name, email FROM users WHERE face_id = %s", (face_id,))
        user = cursor.fetchone()
        cursor.close()
        conn.close()
        return user
    except Exception as e:
        return None

def test_frame(frame, client, settings):
    """Send frame to Rekognition and return match result."""
    # Encode frame as JPEG bytes
    _, buf = cv2.imencode('.jpg', frame, [cv2.IMWRITE_JPEG_QUALITY, 90])
    image_bytes = buf.tobytes()

    try:
        response = client.search_faces_by_image(
            CollectionId=settings.collection_id,
            Image={'Bytes': image_bytes},
            MaxFaces=3,
            FaceMatchThreshold=50
        )
        return response.get('FaceMatches', []), None
    except client.exceptions.InvalidParameterException:
        return [], "No face detected"
    except Exception as e:
        return [], str(e)

def draw_result(frame, matches, error, testing):
    h, w = frame.shape[:2]

    # Draw center guide box
    box_size = min(w, h) // 2
    cx, cy   = w // 2, h // 2
    x1, y1   = cx - box_size//2, cy - box_size//2
    x2, y2   = cx + box_size//2, cy + box_size//2
    cv2.rectangle(frame, (x1, y1), (x2, y2), (100, 100, 255), 2)

    if testing:
        cv2.putText(frame, "Testing...", (20, 40),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 200, 255), 2)
        return frame

    # Instructions
    cv2.putText(frame, "SPACE = Test  |  Q = Quit",
                (10, h - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.55, (200, 200, 200), 1)
    cv2.putText(frame, "Center your face in the box",
                (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (200, 200, 200), 1)

    if error:
        cv2.putText(frame, f"✗ {error}", (10, 70),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
        return frame

    if matches:
        y_offset = 70
        for i, match in enumerate(matches):
            face_id    = match['Face']['FaceId']
            similarity = match['Similarity']
            user       = get_user_by_face_id(face_id)

            if similarity >= 90:
                color = (0, 220, 0)    # green
                verdict = "STRONG MATCH"
            elif similarity >= 70:
                color = (0, 200, 255)  # yellow
                verdict = "WEAK MATCH"
            else:
                color = (0, 100, 255)  # orange
                verdict = "LOW"

            name  = user['name']  if user else "Unknown"
            email = user['email'] if user else face_id[:16] + "..."

            text = f"#{i+1} {similarity:.1f}% — {name} ({email}) [{verdict}]"
            cv2.putText(frame, text, (10, y_offset),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.62, color, 2)
            y_offset += 35

    return frame

def main():
    print("\n" + "="*55)
    print("  LIVE CAMERA FACE MATCH TEST")
    print("="*55)
    print("  SPACE → Capture and test against Rekognition")
    print("  Q     → Quit")
    print("="*55 + "\n")

    # Load AWS
    try:
        settings = get_aws_settings()
        client   = get_rekognition_client()
        print(f"✓ Collection: {settings.collection_id}")
        print(f"✓ Region:     {settings.region}\n")
    except Exception as e:
        print(f"✗ AWS error: {e}")
        sys.exit(1)

    # Open camera
    cap = cv2.VideoCapture(0)
    if not cap.isOpened():
        print("✗ Cannot open camera. Check camera permissions.")
        sys.exit(1)

    cap.set(cv2.CAP_PROP_FRAME_WIDTH,  1280)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)

    matches      = []
    error        = None
    testing      = False
    last_result  = None

    print("Camera open. Press SPACE to test your face.\n")

    while True:
        ret, frame = cap.read()
        if not ret:
            break

        frame = cv2.flip(frame, 1)  # mirror

        # Draw current result overlay
        display = draw_result(frame.copy(), matches, error, testing)
        cv2.imshow("Face Match Test — SPACE to capture, Q to quit", display)

        key = cv2.waitKey(1) & 0xFF

        if key == ord('q') or key == 27:
            break

        elif key == ord(' '):
            print("📷 Capturing and testing...")
            testing = True

            # Show testing frame immediately
            display2 = draw_result(frame.copy(), [], None, True)
            cv2.imshow("Face Match Test — SPACE to capture, Q to quit", display2)
            cv2.waitKey(1)

            matches, error = test_frame(frame, client, settings)
            testing = False

            # Print result to terminal
            print("-" * 55)
            if error:
                print(f"✗ {error}")
            elif not matches:
                print("✗ No matches found (face not registered or below 50% threshold)")
            else:
                for i, match in enumerate(matches):
                    face_id    = match['Face']['FaceId']
                    similarity = match['Similarity']
                    user       = get_user_by_face_id(face_id)
                    name       = user['name']  if user else "Not in DB"
                    email      = user['email'] if user else "-"

                    icon = "✅" if similarity >= 90 else ("⚠️" if similarity >= 70 else "❌")
                    print(f"{icon} Match #{i+1}: {similarity:.1f}%  →  {name}  ({email})")

            print("-" * 55 + "\n")

    cap.release()
    cv2.destroyAllWindows()
    print("Done.")

if __name__ == "__main__":
    main()