import os
import cv2 as cv
import openpyxl
import pyttsx3
import pyautogui
from pyzbar import pyzbar
from datetime import datetime
import requests
# Khởi tạo danh sách rỗng để lưu trữ thông tin người dùng
user_data = []
history = []
screen_width = 1250 
screen_height = 1100
WINDOW_QR_CODE = "QR Code"
WINDOW_TRACKING = "Tracking"
WINDOW_HISTORY = "History"
URL_API = "https://ms.prology.net/api/v1"
data = [0]
# Hàm thông báo bằng giọng nói
def speak(text):
    engine = pyttsx3.init()
    engine.say(text)
    engine.runAndWait()

def send_image(id, file_name):
    # Ensure id is a string if it's an integer
    id = str(id)
    
    today_date = datetime.now().strftime("%Y_%m_%d")
    folder_path = f"./images/{today_date}"
    
    # Ensure the directory exists
    if not os.path.exists(folder_path):
        os.makedirs(folder_path)
    
    # Ensure the full file path is correct
    file_path = os.path.join(folder_path, file_name)
    
    # Check if the file exists
    if not os.path.isfile(file_path):
        print(f"Error: The file {file_path} does not exist.")
        return {"status": False, "message": f"The file {file_path} does not exist."}
    
    with open(file_path, 'rb') as image_file:
        files = {'image': image_file}
        # Correct payload for the data parameter
        data = {'id': id, 'file_name': file_name}
        print(files)
        try:
            response = requests.post(URL_API + "/admin/tracking/send-image", data=data, files=files)
            response.raise_for_status()
            res = response.json()
        except requests.exceptions.RequestException as e:
            print(f"HTTP Request failed: {e}")
            return {"status": False, "message": str(e)}
    
    # Check if the request was successful
    if res.get('status') == True:
        # Process the returned data
        print(res)
        return res
    else:
        return res
def create_history(frame, data):
    # Gửi yêu cầu POST với dữ liệu đã chỉ định
    response = requests.post(URL_API+"/admin/tracking/scan-create", data=data)
    res = response.json()
    # Kiểm tra xem gửi yêu cầu có thành công hay không
    if res.get('status') == True:
        # Xử lý dữ liệu trả về
        print(res)
        return res
    else:
        display_text(frame, res.get('data'), (25, 25), 0.7, (6, 6, 255), 2)
        speak(res.get('data'))
        return res
# Hàm để ghi thông tin vào tệp Excel
def write_to_excel(name, time, check_type):
    try:
        # Mở workbook hiện có
        workbook = openpyxl.load_workbook("./data/"+time.strftime("%Y_%m")+"_check_in_out.xlsx")
        sheet = workbook.active
    except FileNotFoundError:
        # Tạo workbook mới nếu tệp không tồn tại
        workbook = openpyxl.Workbook()
        sheet = workbook.active
        sheet.append(["Name", "Role", "Time", "Check Type"])

    # Ghi thông tin vào các ô trong tệp Excel
    sheet.append([name.split('\n')[0].strip(), name.split('\n')[1].strip(), time, check_type])

    # Lưu tệp Excel
    workbook.save("./data/"+time.strftime("%Y_%m")+"_check_in_out.xlsx")


def check_response(res, frame, name, timestamp, text):
    if res.get('status'):
        display_text(frame, f"{text.split('\n')[0].strip()} {res.get('check_status')}", (25, 25), 0.7, (0, 255, 10), 2)
        display_text(frame, f"{text.split('\n')[1]}", (25, 50), 0.7, (0, 255, 10), 2)
        display_text(frame, f"{datetime.now()}", (25, 75), 0.7, (0, 255, 10), 2)
        display_text(frame, f"Sucessful", (25, 100), 0.7, (0, 255, 10), 2)
        write_to_excel(name, timestamp, res.get('check_status'))
        speak(res.get('check_status') + " success")
        return True
    else:
        display_text(frame, f"Call API fail", (25, 50), 0.7, (6, 6, 255), 2)
        speak("Call API fail")
        cv.waitKey(2000)
        return False
    
# Hàm để thêm thông tin mới vào danh sách
def check_in(name, frame, text):
    timestamp = datetime.now()
    user_data.append({"name": name, "check_in_time": timestamp})
    res = create_history(frame, {"name": name.split('\n')[0], "time_string": f"{datetime.now()}", "status": "check in"})
    result = check_response(res, frame, name, timestamp, text)
    return res
    # cv.waitKey(5000)

    
# Hàm để xóa thông tin khi check out
def check_out(name, frame, text):
    for user in user_data:
        if user["name"] == name:
            timestamp = datetime.now()
            user["check_out_time"] = timestamp
            print(f"{name} đã check out lúc {timestamp}")
            user_data.remove(user)
            res = create_history(frame, {"name": name.split('\n')[0], "time_string": f"{datetime.now()}", "status": "check out"})
            result = check_response(res, frame, name, timestamp, text)
            if result:
                return res
# Hàm để hiển thị văn bản lên hình ảnh
def display_text(frame, text, position, font_scale, color, thickness):
    cv.putText(frame, text, position, cv.FONT_HERSHEY_COMPLEX, font_scale, color, thickness)

def screenshot_window(save_path):
        today_date = datetime.now().strftime("%Y_%m_%d")
        folder_path = f"./images/{today_date}"
        # Kiểm tra xem thư mục đã tồn tại chưa
        if not os.path.exists(folder_path):
            # Nếu thư mục chưa tồn tại, tạo mới
            os.makedirs(folder_path)
            print(f"Folder '{today_date}' created successfully!")

        screenshot = pyautogui.screenshot(region=(10, 10, screen_width, screen_height))
        screenshot.save(folder_path+"/"+save_path)
        print("Screenshot saved successfully!")

# Hàm để xử lý quá trình quét mã QR code
def process_qr_code(frame):
    decoded_objects = pyzbar.decode(frame)
    for obj in decoded_objects:
        (x, y, w, h) = obj.rect
        cv.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 255), 2)
        text = obj.data.decode('utf-8')
        file_name = ""
        status = ""
        id_log = 0

        if text.endswith("\n\n"):
            if text not in [user["name"] for user in user_data]:
                print(f"{text} đã check in lúc {datetime.now()}")
                status += "check in"
                file_name+=text.split('\n')[0]+"_"+f"{status}_at_{datetime.now().strftime("%Y_%m_%d_%H_%M_%S")}.png"
                # screenshot_window(file_name)
                res = check_in(text, frame, text)
                id_log = res.get('data').get('id')
            else:
                print(f"{text} đã check out lúc {datetime.now()}")
                status += "check out"
                file_name+=text.split('\n')[0]+"_"+f"{status}_at_{datetime.now().strftime("%Y_%m_%d_%H_%M_%S")}.png"
                # screenshot_window(file_name)
                res = check_out(text, frame, text)
                id_log = res.get('data').get('id')
            cv.namedWindow(WINDOW_QR_CODE, cv.WINDOW_NORMAL)
            cv.resizeWindow(WINDOW_QR_CODE, screen_width, screen_height)
            cv.imshow(WINDOW_QR_CODE, frame)
            cv.moveWindow(WINDOW_QR_CODE, 10, 10)
            cv.waitKey(5000)  # Chờ 5 giây
            screenshot_window(file_name)
            send_image(id_log, file_name)
            cv.destroyWindow(WINDOW_QR_CODE)
        else:
            display_text(frame, f"QR invalid", (25, 25), 0.7, (6, 6, 255), 2)
            display_text(frame, f"Failed", (25, 50), 0.7, (6, 6, 255), 2)
            speak("Failed")   
            cv.namedWindow(WINDOW_QR_CODE, cv.WINDOW_NORMAL)
            cv.resizeWindow(WINDOW_QR_CODE, screen_width, screen_height)
            cv.imshow(WINDOW_QR_CODE, frame)
            cv.moveWindow(WINDOW_QR_CODE, 10, 10)
            cv.waitKey(2000)
            cv.destroyWindow(WINDOW_QR_CODE)
    return frame

# Khởi tạo camera
def main():
    cap = cv.VideoCapture(0)
    face_cascade = cv.CascadeClassifier(cv.data.haarcascades + 'haarcascade_frontalface_default.xml')
    cv.namedWindow(WINDOW_TRACKING, cv.WINDOW_NORMAL)
    cv.resizeWindow(WINDOW_TRACKING, screen_width, screen_height)
    while True:
        ret, frame = cap.read()
        if not ret:
            break
        # Convert the frame to grayscale
        gray_frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)

        # Detect faces in the frame
        faces = face_cascade.detectMultiScale(gray_frame, scaleFactor=1.1, minNeighbors=25, minSize=(30, 30))

        # Draw rectangles around the faces
        if len(faces) == 1:
            for (x, y, w, h) in faces:
                cv.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2)
                display_text(frame, f"Face detected", (430, 25), 0.7, (0, 255, 0), 2)
                frame = process_qr_code(frame)
        else:
            display_text(frame, f"Face not found", (430, 25), 0.7, (6, 6, 255), 2)
        cv.imshow(WINDOW_TRACKING, frame)
        cv.moveWindow(WINDOW_TRACKING, 10, 10)
        if cv.waitKey(1) == ord('q'):
            break

    cap.release()
    cv.destroyAllWindows()

main()