#!/usr/bin/env python3
"""
Simple Test Server
This is a simplified version that just handles face recognition.
"""
from flask import Flask, request, jsonify
from flask_cors import CORS
import cv2
import numpy as np
import base64
import os
import json
import datetime
import csv

app = Flask(__name__)
CORS(app)

@app.route('/recognize', methods=['POST'])
def recognize_face():
    """Simple face recognition endpoint"""
    try:
        data = request.get_json()
        if not data or 'image' not in data:
            return jsonify({'error': 'No image data provided'}), 400
        
        # Decode base64 image
        image_data = data['image'].split(',')[1] if ',' in data['image'] else data['image']
        image_bytes = base64.b64decode(image_data)
        
        # Convert to numpy array
        nparr = np.frombuffer(image_bytes, np.uint8)
        img = cv2.imdecode(nparr, cv2.IMREAD_GRAYSCALE)
        
        if img is None:
            return jsonify({'error': 'Failed to decode image'}), 400
        
        print(f"Debug - Image loaded: {img.shape}")
        
        # Preprocess the image (same as working test script)
        from livestream import preprocess_face
        face_img = preprocess_face(img)
        print(f"Debug - Image preprocessed: {face_img.shape}")
        
        # Load and use the recognizer
        try:
            recognizer = cv2.face.LBPHFaceRecognizer_create()
            model_file = "face_recognizer.yml"
            
            if not os.path.exists(model_file):
                return jsonify({'error': 'Model file not found. Train the model first.'}), 400
            
            recognizer.read(model_file)
            print("Debug - Model loaded successfully")
            
            # Call predict method
            print("Debug - About to call predict")
            prediction_result = recognizer.predict(face_img)
            print(f"Debug - Prediction result: {prediction_result}")
            print(f"Debug - Result type: {type(prediction_result)}")
            
            # Handle the result
            if isinstance(prediction_result, tuple) and len(prediction_result) == 2:
                user_id, confidence = prediction_result
                print(f"Debug - Successfully unpacked: user_id={user_id}, confidence={confidence}")
            else:
                # Fallback
                user_id = prediction_result
                confidence = 0.0
                print(f"Debug - Using fallback: user_id={user_id}, confidence={confidence}")
            
            # Confidence threshold
            confidence_threshold = 150
            print(f"Debug - User ID: {user_id}, Confidence: {confidence}, Threshold: {confidence_threshold}")
            
            if confidence < confidence_threshold:
                # Get user name from user_data.json
                user_name = "Unknown"
                try:
                    if os.path.exists("user_data.json"):
                        with open("user_data.json", "r") as f:
                            user_data = json.load(f)
                            if str(user_id) in user_data:
                                user_name = user_data[str(user_id)]["name"]
                                print(f"Debug - Found user name: {user_name}")
                            else:
                                print(f"Debug - User ID {user_id} not found in user_data.json")
                except Exception as e:
                    print(f"Debug - Error reading user_data.json: {e}")
                
                # Log attendance with proper check-in/check-out logic
                now = datetime.datetime.now()
                timestamp = now.strftime("%Y-%m-%d %H:%M:%S")
                date_only = now.strftime("%Y-%m-%d")
                
                log_file = "attendance_log.csv"
                if not os.path.exists(log_file):
                    with open(log_file, "w", newline="") as file:
                        writer = csv.writer(file)
                        writer.writerow(["Date", "User ID", "User Name", "Check-in", "Check-out"])
                
                # Read existing attendance data
                existing_records = {}
                if os.path.exists(log_file):
                    with open(log_file, "r", newline="") as file:
                        reader = csv.DictReader(file)
                        for row in reader:
                            record_date = row.get('Date', '')
                            record_user_id = row.get('User ID', '')
                            if record_date == date_only and record_user_id == str(user_id):
                                existing_records[record_user_id] = row
                
                # Determine if this is check-in or check-out
                if str(user_id) not in existing_records:
                    # First recognition of the day - create check-in record
                    with open(log_file, "a", newline="") as file:
                        writer = csv.writer(file)
                        writer.writerow([date_only, user_id, user_name, timestamp, ""])
                    print(f"Debug - Check-in logged: {user_name} (ID: {user_id}) at {timestamp}")
                else:
                    # Subsequent recognition - update check-out time
                    # Read all records and update the specific one
                    all_records = []
                    with open(log_file, "r", newline="") as file:
                        reader = csv.DictReader(file)
                        headers = reader.fieldnames
                        for row in reader:
                            if (row.get('Date', '') == date_only and 
                                row.get('User ID', '') == str(user_id)):
                                # Update check-out time
                                row['Check-out'] = timestamp
                            all_records.append(row)
                    
                    # Rewrite the file with updated records
                    with open(log_file, "w", newline="") as file:
                        writer = csv.DictWriter(file, fieldnames=headers)
                        writer.writeheader()
                        writer.writerows(all_records)
                    print(f"Debug - Check-out updated: {user_name} (ID: {user_id}) at {timestamp}")
                
                # Return success response (same format as original server)
                return jsonify({
                    'success': True,
                    'user_id': int(user_id),
                    'user_name': user_name,
                    'confidence': round(confidence, 2),
                    'timestamp': timestamp,
                    'message': f'User {user_name} (ID: {user_id}) recognized successfully'
                })
            else:
                # Return failure response
                return jsonify({
                    'success': False,
                    'message': 'Face not recognized - confidence too low',
                    'confidence': round(confidence, 2),
                    'debug_info': f'Confidence {confidence} >= threshold {confidence_threshold} (lower is better in LBPH)'
                })
                
        except Exception as e:
            print(f"Debug - Error in recognition: {e}")
            return jsonify({'error': f'Recognition error: {str(e)}'}), 500
            
    except Exception as e:
        print(f"Debug - General error: {e}")
        return jsonify({'error': f'Server error: {str(e)}'}), 500

@app.route('/admin/users', methods=['GET'])
def get_all_users():
    """Get all registered users"""
    try:
        users = []
        if os.path.exists("user_data.json"):
            with open("user_data.json", "r") as f:
                user_data = json.load(f)
                
            for user_id, user_info in user_data.items():
                # Count images for this user
                user_folder = f"registered_faces/{user_id}"
                image_count = 0
                if os.path.exists(user_folder):
                    for root, dirs, files in os.walk(user_folder):
                        image_count += len([f for f in files if f.lower().endswith(('.jpg', '.jpeg', '.png'))])
                
                users.append({
                    'user_id': int(user_id),
                    'name': user_info.get('name', 'Unknown'),
                    'image_count': image_count,
                    'status': 'Active' if image_count > 0 else 'Inactive'
                })
        
        return jsonify({"users": users})
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/admin/users/<user_id>/images', methods=['GET'])
def get_user_images(user_id):
    """Get all images for a specific user"""
    try:
        images = []
        user_folder = f"registered_faces/{user_id}"
        
        if os.path.exists(user_folder):
            for root, dirs, files in os.walk(user_folder):
                for file in files:
                    if file.lower().endswith(('.jpg', '.jpeg', '.png')):
                        rel_path = os.path.relpath(os.path.join(root, file), user_folder)
                        subdir = os.path.dirname(rel_path) if os.path.dirname(rel_path) else 'root'
                        
                        images.append({
                            'filename': file,
                            'path': rel_path,
                            'subdirectory': subdir
                        })
        
        return jsonify(images)
    except Exception as e:
        return jsonify({'error': str(e)}), 500

@app.route('/attendance/data', methods=['GET'])
def get_attendance_data():
    """Get detailed attendance data for reports with proper check-in/check-out logic"""
    try:
        import datetime
        import csv
        
        attendance_data = []
        
        # Read attendance log if it exists
        log_file = "attendance_log.csv"
        if os.path.exists(log_file):
            with open(log_file, 'r', newline='') as file:
                reader = csv.DictReader(file)
                for row in reader:
                    date = row.get('Date', '')
                    user_id = row.get('User ID', 'Unknown')
                    user_name = row.get('User Name', 'Unknown')
                    checkin = row.get('Check-in', '')
                    checkout = row.get('Check-out', '')
                    
                    if date and checkin:
                        try:
                            # Parse check-in time
                            checkin_dt = datetime.datetime.strptime(checkin, "%Y-%m-%d %H:%M:%S")
                            
                            # Calculate duration if check-out exists
                            duration = 'N/A'
                            status = 'Present'
                            
                            if checkout:
                                checkout_dt = datetime.datetime.strptime(checkout, "%Y-%m-%d %H:%M:%S")
                                time_diff = checkout_dt - checkin_dt
                                hours = int(time_diff.total_seconds() // 3600)
                                minutes = int((time_diff.total_seconds() % 3600) // 60)
                                duration = f"{hours}h {minutes}m"
                                
                                # Determine status based on duration
                                if hours >= 8:
                                    status = 'Present'
                                elif hours >= 4:
                                    status = 'Half-day'
                                else:
                                    status = 'Late'
                            
                            # Create attendance record
                            attendance_data.append({
                                'date': date,
                                'user': user_name,
                                'checkin': checkin_dt.strftime("%I:%M %p"),
                                'checkout': checkout_dt.strftime("%I:%M %p") if checkout else 'N/A',
                                'duration': duration,
                                'status': status
                            })
                        except ValueError as e:
                            print(f"Debug - Error parsing date: {e}, row: {row}")
                            continue
        
        return jsonify({'attendance': attendance_data})
        
    except Exception as e:
        print(f"Debug - Error getting attendance data: {e}")
        return jsonify({'error': f'Error getting attendance data: {str(e)}'}), 500

@app.route('/admin/users/<user_id>/images/<path:image_path>', methods=['GET'])
def get_user_image(user_id, image_path):
    """Serve a specific user image"""
    try:
        from flask import send_file
        image_file = f"registered_faces/{user_id}/{image_path}"
        if os.path.exists(image_file):
            return send_file(image_file, mimetype='image/jpeg')
        else:
            return jsonify({'error': 'Image not found'}), 404
    except Exception as e:
        return jsonify({'error': str(e)}), 500

if __name__ == '__main__':
    print("Starting Simple Test Server...")
    print("This server skips face detection and just preprocesses the whole image")
    print("It now includes user name lookup and attendance logging")
    app.run(host='127.0.0.1', port=5001, debug=True)
