import os, time, face_recognition, numpy as np
from flask import Flask, request
from PIL import Image
from io import BytesIO
from utils import rotate_image, response_formatter, allowed_file, face_eval, face_eval_regis
from translations import trans

# import uuid
# from werkzeug.utils import secure_filename

dirname = os.getcwd()
attendance_folder = os.path.join(dirname, 'users', 'attendance')

if not os.path.exists(attendance_folder):
    os.makedirs(attendance_folder)
    
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = attendance_folder

@app.route("/")
def helloWorld():
    return "hello world"

@app.route('/compare_faces', methods=['POST'])
def match_attendance():
    try:
        lang = request.headers.get('Accept-Language', 'en')
        
        if 'image_1' not in request.files or 'image_2' not in request.files:
            message = trans[lang]['req_file_name']
            return response_formatter(message, 'failed')

        req_image_1 = request.files['image_1']
        req_image_2 = request.files['image_2']

        if not (allowed_file(req_image_1.filename) and allowed_file(req_image_2.filename)):
            message = trans[lang]['allowed_extension']
            return response_formatter(message, 'failed')

        # # detect spoofing
        # result = detect(app.config['UPLOAD_FOLDER'], req_image_2)
        # if(result):
        #     return response_formatter('Verifikasi gagal, pastikan mengambil foto di tempat yang cukup cahaya', 'failed')
        
        # load image
        image_1 = face_recognition.load_image_file(req_image_1) 
        image_2 = face_recognition.load_image_file(req_image_2) 

        # deteksi wajah
        face_locations_1 = face_recognition.face_locations(image_1)
        face_locations_2 = face_recognition.face_locations(image_2)
        # Rotate images if faces are not detected
        if not face_locations_1:
            image_1 = rotate_image(req_image_1)
            face_locations_1 = face_recognition.face_locations(image_1)
            if not face_locations_1:
                message = trans[lang]['face_1_not_found']
                return response_formatter(message, 'failed')

        if not face_locations_2:
            image_2 = rotate_image(req_image_2)
            face_locations_2 = face_recognition.face_locations(image_2)
            if not face_locations_2:
                message = trans[lang]['face_2_not_found']
                return response_formatter(message, 'failed')

        # evaluasi attendance image
        if len(face_locations_2) == 1:
            eval_attendance = face_eval(image_2, face_locations_2, min_wide_face_area=15000, laplacian_thresold=85, lang=lang)
            # print(eval_attendance)
            if eval_attendance['result'] == False:
                return response_formatter(eval_attendance['message'], eval_attendance['status'])
        elif len(face_locations_2) > 1:
            return response_formatter(trans[lang]['only_one_face'], 'failed', False)
        
        # encoding image agar bisa di lakukan komparasi
        image_1_encodings = face_recognition.face_encodings(image_1, model='large')[0]
        image_2_encodings = face_recognition.face_encodings(image_2, model='large')[0]

        # compare image
        match_result = face_recognition.compare_faces([image_1_encodings], image_2_encodings, tolerance=0.5)
        
        # Check and create folder if not exists
        folder_path = os.path.join(app.config['UPLOAD_FOLDER'], req_image_2.filename.split('.')[0])
        if not os.path.exists(folder_path):
            os.makedirs(folder_path)
        existing_files = [f for f in os.listdir(folder_path) if f.endswith('.jpg')]
                
        if match_result[0]:
            # save attendance foto to users/attendance folder, max 5 file  
            if len(existing_files) < 5:
                path = os.path.join(folder_path, time.strftime("%Y%m%d_%H%M%S") + '.jpg')
                req_image_2.seek(0)
                req_image_2.save(path)
                    
            status = 'success'
            message = trans[lang]['face_match']
        else:
            status = 'failed'
            message = trans[lang]['face_not_match']
            
            if len(existing_files) > 0:
                for f in existing_files:
                    # print(f)
                    image_1 = face_recognition.load_image_file(os.path.join(folder_path, f))
                    image_1_encodings = face_recognition.face_encodings(image_1, model='large')[0]
                    match_result = face_recognition.compare_faces([image_1_encodings], image_2_encodings, tolerance=0.5)
                    if match_result[0]:
                        status = 'success'
                        message = trans[lang]['face_match']
                        break        

        return response_formatter(message, status, bool(match_result[0]))

    except Exception as e:
        return response_formatter(str(e), 'failed')


@app.route('/find_faces', methods=['POST'])
def find_faces():
    try:
        lang = request.form.get('lang', 'en')
        req_image = request.files['image']
        
        ############### testing save gambar ##################
        # unique_filename = 'reg_' + str(uuid.uuid4()) + '_' + secure_filename(req_image.filename)
        # path = os.path.join(attendance_folder, unique_filename)
        # req_image.save(path)
        #################################
        
        loadedImage = face_recognition.load_image_file(req_image)
        
        faces = face_recognition.face_locations(loadedImage) # faces akan berisi list lokasi wajah

        if not faces:
            # coba rotasi jika tidak ada wajah
            req_image.seek(0) # Pindahkan kursor ke awal byte
            file_bytes = BytesIO(req_image.read())
            image = Image.open(file_bytes).rotate(90)
            image.convert('RGB')
          
            # faces = face_recognition.load_image_file(file_bytes) # jangan di load lagi dengan face_recog karena sudah di open dengan Pill.Image
            faces = face_recognition.face_locations(np.array(image))
            
        if len(faces) == 1: #hanya satu wajah yang di ijinkan
           data = face_eval_regis(loadedImage, faces, min_wide_face_area=15000, laplacian_thresold=85)
           return response_formatter(data['message'], data['status'], data['result'])
       
        elif len(faces) > 1 :
          
            return response_formatter(trans[lang]['only_one_face'], 'failed')
        else:
            return response_formatter(trans[lang]['face_not_found'], 'failed')
            
    except Exception as e:
        return response_formatter(str(e), 'failed')
    
@app.route('/testing', methods=['POST'])
def testing():
 
    if 'image_1' not in request.files or 'image_2' not in request.files:
        message = 'request file must have name image_1 and image_2'
        return response_formatter(message, 'failed')

    req_image_1 = request.files['image_1']
    req_image_2 = request.files['image_2']

    if not (allowed_file(req_image_1.filename) and allowed_file(req_image_2.filename)):
        message = 'Hanya ekstensi berikut yang diperbolehkan: jpg, jpeg, png, webp'
        return response_formatter(message, 'failed')

    # load image
    image_1 = face_recognition.load_image_file(req_image_1) 
    image_2 = face_recognition.load_image_file(req_image_2) 

    # deteksi wajah
    face_locations_1 = face_recognition.face_locations(image_1)
    face_locations_2 = face_recognition.face_locations(image_2)
    
    if not face_locations_1:
        message = 'Faces not detected in the source image.'
        return response_formatter(message, 'failed')

    if not face_locations_2:
        message = 'Faces not detected in the requested image.'
        return response_formatter(message, 'failed')
    
    # encoding image agar bisa di lakukan komparasi
    image_1_encodings = face_recognition.face_encodings(image_1, model='large')[0]
    image_2_encodings = face_recognition.face_encodings(image_2, model='large')[0]

    # compare image
    match_result = face_recognition.compare_faces([image_1_encodings], image_2_encodings, tolerance=0.39)
    print(match_result)
    if match_result[0]:
        status = 'success'
        message = 'Facial recognition is match.'
    else:
        status = 'failed'
        message = 'Facial recognition does not match.'

    return response_formatter(message, status, bool(match_result[0]))

    