#!/usr/bin/env python3
"""
Simple Face Recognition App - Minimal GUI version
Designed to work reliably on macOS
"""

import cv2
import numpy as np
import os
import json
import csv
import time
from datetime import datetime, date

def load_user_data():
    """Load user data from user_data.json"""
    try:
        if os.path.exists("user_data.json"):
            with open("user_data.json", "r") as f:
                return json.load(f)
        return {}
    except Exception as e:
        print(f"❌ Error loading user data: {e}")
        return {}

def load_recognizer():
    """Load the face recognizer model"""
    try:
        recognizer = cv2.face.LBPHFaceRecognizer_create()
        model_file = "face_recognizer.yml"
        
        if os.path.exists(model_file):
            recognizer.read(model_file)
            print("✅ Loaded face recognition model")
            return recognizer
        else:
            print("⚠️ Face recognition model not found")
            return None
    except Exception as e:
        print(f"❌ Error loading recognizer: {e}")
        return None

def log_attendance(user_id, user_name, attendance_data):
    """Log attendance with check-in/check-out logic"""
    try:
        today = date.today().strftime("%Y-%m-%d")
        
        if today not in attendance_data:
            attendance_data[today] = {}
        
        if user_name not in attendance_data[today]:
            # First time today - check-in
            attendance_data[today][user_name] = {
                "checkin": datetime.now().strftime("%H:%M:%S"),
                "checkout": "Not checked out"
            }
            print(f"✅ {user_name} checked in at {attendance_data[today][user_name]['checkin']}")
            return "Check-in"
        else:
            # Already checked in today - check-out
            if attendance_data[today][user_name]["checkout"] == "Not checked out":
                attendance_data[today][user_name]["checkout"] = datetime.now().strftime("%H:%M:%S")
                print(f"✅ {user_name} checked out at {attendance_data[today][user_name]['checkout']}")
                return "Check-out"
            else:
                # Update existing checkout time
                attendance_data[today][user_name]["checkout"] = datetime.now().strftime("%H:%M:%S")
                print(f"✅ {user_name} checkout updated to {attendance_data[today][user_name]['checkout']}")
                return "Check-out (Updated)"
    except Exception as e:
        print(f"❌ Error logging attendance: {e}")
        return "Error"

def save_attendance_to_csv(attendance_data):
    """Save attendance data to CSV file"""
    try:
        with open("attendance_log.csv", "w", newline="") as csvfile:
            fieldnames = ["Date", "Name", "Check-in", "Check-out"]
            writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
            
            writer.writeheader()
            for date_str, users in attendance_data.items():
                for user_name, times in users.items():
                    writer.writerow({
                        "Date": date_str,
                        "Name": user_name,
                        "Check-in": times["checkin"],
                        "Check-out": times["checkout"]
                    })
    except Exception as e:
        print(f"❌ Error saving attendance to CSV: {e}")

def main():
    """Main face recognition loop"""
    print("🚀 Starting Simple Face Recognition System")
    print("=" * 50)
    
    # Load data
    user_data = load_user_data()
    recognizer = load_recognizer()
    attendance_data = {}
    
    if not user_data:
        print("❌ No user data found. Please register users first.")
        return
    
    if not recognizer:
        print("❌ No face recognition model found. Please train the model first.")
        return
    
    print(f"✅ Loaded {len(user_data)} users")
    print("📋 Registered users:")
    for user_id, user_info in user_data.items():
        print(f"   - ID: {user_id}, Name: {user_info.get('name', 'Unknown')}")
    
    # Initialize camera
    print("\n📷 Initializing camera...")
    cap = cv2.VideoCapture(0)
    
    if not cap.isOpened():
        print("❌ Failed to open camera")
        return
    
    # Set camera properties
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
    cap.set(cv2.CAP_PROP_FPS, 30)
    
    print("✅ Camera initialized successfully")
    print("\n🎯 Face Recognition Active!")
    print("📝 Instructions:")
    print("   - Position your face in front of the camera")
    print("   - The system will detect and recognize faces automatically")
    print("   - Press 'q' to quit")
    print("   - Press 's' to show statistics")
    print("=" * 50)
    
    # Statistics
    total_detections = 0
    successful_recognitions = 0
    confidence_threshold = 120  # LBPH: lower is better, increased for better accuracy
    
    # Face cascade
    face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
    
    try:
        while True:
            ret, frame = cap.read()
            if not ret:
                continue
            
            # Flip frame horizontally for mirror effect
            frame = cv2.flip(frame, 1)
            
            # Convert to grayscale for face detection
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            
            # Detect faces
            faces = face_cascade.detectMultiScale(gray, 1.1, 4)
            
            # Process each face
            for (x, y, w, h) in faces:
                total_detections += 1
                
                # Draw rectangle around face
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                
                # Face recognition with improved preprocessing
                face_roi = gray[y:y + h, x:x + w]
                face_roi = cv2.resize(face_roi, (200, 200))  # Increased size for better accuracy
                face_roi = cv2.equalizeHist(face_roi)  # Histogram equalization for better contrast
                
                try:
                    label, confidence = recognizer.predict(face_roi)
                    
                    if confidence < confidence_threshold:
                        # Face recognized
                        user_name = user_data.get(str(label), {}).get("name", f"User_{label}")
                        
                        # Add labels
                        cv2.putText(frame, f"User: {user_name}", (x, y - 10), 
                                  cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
                        cv2.putText(frame, f"Confidence: {confidence:.1f}", (x, y + h + 20), 
                                  cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
                        
                        # Log attendance (only once per session to avoid spam)
                        if not hasattr(main, 'last_recognized') or main.last_recognized != (label, user_name):
                            status = log_attendance(label, user_name, attendance_data)
                            save_attendance_to_csv(attendance_data)
                            print(f"📝 {user_name} - {status}")
                            main.last_recognized = (label, user_name)
                            successful_recognitions += 1
                        
                    else:
                        # Face not recognized
                        cv2.putText(frame, "Unknown", (x, y - 10), 
                                  cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
                        cv2.putText(frame, f"Confidence: {confidence:.1f}", (x, y + h + 20), 
                                  cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
                        
                except Exception as e:
                    print(f"Recognition error: {e}")
                    cv2.putText(frame, "Error", (x, y - 10), 
                              cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
            
            # Add statistics overlay
            cv2.putText(frame, f"Detections: {total_detections}", (10, 30), 
                      cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
            cv2.putText(frame, f"Recognitions: {successful_recognitions}", (10, 60), 
                      cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 2)
            cv2.putText(frame, "Press 'q' to quit, 's' for stats", (10, frame.shape[0] - 20), 
                      cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
            
            # Display frame
            cv2.imshow('Simple Face Recognition System', frame)
            
            # Handle key presses
            key = cv2.waitKey(1) & 0xFF
            if key == ord('q'):
                break
            elif key == ord('s'):
                print("\n📊 Current Statistics:")
                print(f"   Total Detections: {total_detections}")
                print(f"   Successful Recognitions: {successful_recognitions}")
                print(f"   Recognition Rate: {(successful_recognitions/total_detections*100):.1f}%" if total_detections > 0 else "   Recognition Rate: 0%")
                print(f"   Confidence Threshold: {confidence_threshold}")
                print("=" * 30)
    
    except KeyboardInterrupt:
        print("\n⏹️ Interrupted by user")
    
    finally:
        # Cleanup
        cap.release()
        cv2.destroyAllWindows()
        
        print("\n📊 Final Statistics:")
        print(f"   Total Detections: {total_detections}")
        print(f"   Successful Recognitions: {successful_recognitions}")
        print(f"   Recognition Rate: {(successful_recognitions/total_detections*100):.1f}%" if total_detections > 0 else "   Recognition Rate: 0%")
        
        print("\n✅ Face recognition session ended")
        print("📁 Attendance data saved to attendance_log.csv")

if __name__ == "__main__":
    main()
