import sys
import os
import ctypes
import time
import sqlite3
import psutil
import win32gui
from PyQt5.QtWidgets import QTextEdit,QSplitter, QLineEdit, QFrame, QApplication, QSizePolicy, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QComboBox, QMessageBox, QAction, QDialog
from PyQt5.QtCore import Qt, QDateTime, QThread, pyqtSignal,QTimer
from PyQt5.QtGui import QPixmap, QFont, QIcon
from pynput import mouse, keyboard
from qt_material import apply_stylesheet
from PIL import ImageGrab
from MainReportLocal import MainReportLocal
import requests
import socket
import urllib3
from PyQt5.QtGui import QStandardItemModel, QStandardItem
from  ProjectInfo import  ProjectInfo
from  TaskInfo import  TaskInfo
from  MainReportSend import  MainReportSend
import json
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
from win32com.client import Dispatch
import pythoncom


# ایجاد دیتابیس و جدول گزارشات
def init_db():
    conn = sqlite3.connect('reports.db')
    cursor = conn.cursor()
    cursor.execute('''
           CREATE TABLE IF NOT EXISTS reports (
            id INTEGER PRIMARY KEY,
            timestamp TEXT,
            screenshot_file TEXT,
            active_project TEXT,
            active_task TEXT,
            mouse_clicks INTEGER,
            keyboard_clicks INTEGER,
            appname TEXT,
            tabtitle TEXT,
            projectId TEXT,
            taskId TEXT
        )
    ''')
    conn.commit()
    conn.close()


class ShiftThread(QThread):
    count_updated = pyqtSignal(int, int)

    def __init__(self):
        super().__init__()
        self.mouse_clicks = 0
        self.keyboard_clicks = 0
        self.running = False

    def on_click(self, x, y, button, pressed):
        if self.running and pressed:
            self.mouse_clicks += 1
            self.count_updated.emit(self.mouse_clicks, self.keyboard_clicks)

    def on_press(self, key):
        if self.running:
            self.keyboard_clicks += 1
            self.count_updated.emit(self.mouse_clicks, self.keyboard_clicks)

    def run(self):
        self.running = True
        try:
            with mouse.Listener(on_click=self.on_click) as self.mouse_listener, keyboard.Listener(
                    on_press=self.on_press) as self.keyboard_listener:
                while self.running:
                    time.sleep(0.1)
        finally:
            self.mouse_listener.stop()
            self.keyboard_listener.stop()

    def stop(self):
        self.running = False


class ScreenshotThread(QThread):
    def __init__(self, interval=10, shift_widget=None):
        super().__init__()
        self.interval = interval
        self.running = False
        self.shift_widget = shift_widget

        # تعریف نمونه `ReportThread`
        self.report_thread = ReportThread(self.shift_widget)
        self.report_thread.finished.connect(self.on_report_finished)

    def run(self):
        self.running = True
        while self.running:
            self.take_screenshot()
            time.sleep(self.interval)

    def stop(self):
        self.running = False

    def get_active_window_info(self):
        try:
            # مقداردهی اولیه کتابخانه COM
            pythoncom.CoInitialize()

            # دریافت اطلاعات پنجره فعال
            hwnd = ctypes.windll.user32.GetForegroundWindow()
            pid = ctypes.c_ulong()
            ctypes.windll.user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
            process = psutil.Process(pid.value)
            window_title = win32gui.GetWindowText(hwnd)
            exe_path = process.exe()

            if exe_path is None:
                return "No active program found"

            exe_name = os.path.basename(exe_path)

            # دریافت مسیر میانبرهای منوی استارت
            start_menu_paths = [
                os.path.join(os.getenv('APPDATA'), r'Microsoft\Windows\Start Menu\Programs'),
                os.path.join(os.getenv('PROGRAMDATA'), r'Microsoft\Windows\Start Menu\Programs')
            ]

            shortcuts = {}
            for path in start_menu_paths:
                for root, _, files in os.walk(path):
                    for file in files:
                        if file.endswith('.lnk'):
                            shortcut_path = os.path.join(root, file)
                            shell = Dispatch('WScript.Shell')
                            shortcut = shell.CreateShortcut(shortcut_path)
                            target_path = shortcut.Targetpath
                            if target_path:
                                exe_name_shortcut = os.path.basename(target_path)
                                display_name = file.replace('.lnk', '')
                                shortcuts[exe_name_shortcut] = display_name

            display_name = shortcuts.get(exe_name, exe_name)
            return display_name, window_title
        except Exception as e:
            print(f"Error: {e}")
            return None, None

    def take_screenshot(self):
        projectId = 0
        taskId = 0
        try:
            # گرفتن نام برنامه و عنوان تب فعال
            appname, tabtitle = self.get_active_window_info()
        except:
            print("error Get name App")
        try:
            selected_task_index = self.shift_widget.project_combo.currentIndex()
            projectId = self.shift_widget.project_combo.itemData(selected_task_index, Qt.UserRole)
            selected_task_index = self.shift_widget.task_combo.currentIndex()
            taskId = self.shift_widget.task_combo.itemData(selected_task_index, Qt.UserRole)

        except:
            print("error get Id")
        try:
            screenshot = ImageGrab.grab()
            timestamp = int(time.time())
            if not os.path.exists('screenshots'):
                os.makedirs('screenshots')
            screenshot_file = f'screenshots/screenshot_{timestamp}.png'
            screenshot.save(screenshot_file)



            # ذخیره اطلاعات اسکرین‌شات در دیتابیس
            conn = sqlite3.connect('reports.db')
            cursor = conn.cursor()
            cursor.execute('''
                 INSERT INTO reports (timestamp, screenshot_file, active_project, active_task, mouse_clicks, keyboard_clicks, appname, tabtitle,projectId,taskId)
            VALUES (?, ?, ?, ?, ?, ?, ?, ?,?,?)
            ''', (
                QDateTime.currentDateTime().toString(Qt.DefaultLocaleLongDate),
                screenshot_file,
                self.shift_widget.project_combo.currentText(),
                self.shift_widget.task_combo.currentText(),
                self.shift_widget.shift_thread.mouse_clicks,
                self.shift_widget.shift_thread.keyboard_clicks,
                appname,
                tabtitle,
                str(projectId),
                str(taskId),
            ))
            conn.commit()
            conn.close()
            # شروع `ReportThread` برای ارسال گزارش‌ها به سرور
            self.report_thread.start()
        except Exception as e:
            print(f"Error taking screenshot: {e}")

    def on_report_finished(self, result):
        if result:
            print("گزارش‌ها با موفقیت ارسال شدند.")
        else:
            print("خطا در ارسال گزارش‌ها.")


class ReportThread(QThread):
    finished = pyqtSignal(bool)  # سیگنال برای اتمام عملیات

    def __init__(self, shift_widget):
        super().__init__()
        self.shift = shift_widget

    def run(self):
        result = self.send_reports_to_server()
        self.finished.emit(result)

    def send_reports_to_server(self):
        try:
            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

            # اتصال به دیتابیس
            conn = sqlite3.connect('reports.db')
            cursor = conn.cursor()

            # انتخاب همه رکوردها از جدول reports
            cursor.execute("SELECT * FROM reports")
            records = cursor.fetchall()

            # باز کردن فایل تصویر به صورت باینری
            info_connection = get_client_info()
            with open("data.json", "r", encoding='utf-8') as file:
                data = json.load(file)

            # دریافت فیلد host
            host = "https://" + data.get("host")

            with open("login.json", "r", encoding='utf-8') as file:
                login = json.load(file)

            # دریافت فیلد token
            token = login.get("token")
            url = f"{host}/Frogment/Apis/ReportForShift"
            print(self.shift.shiftId)
            for record in records:
                record_id, timestamp, screenshot_file, active_project, active_task, mouse_clicks, keyboard_clicks, appname, tabtitle,projectId,taskId = record
                dataActive = {
                    'timestamp': timestamp,
                    'active_project': active_project,
                    'active_task': active_task,
                    'mouse_clicks': mouse_clicks,
                    'keyboard_clicks': keyboard_clicks,
                    'appname': appname,
                    'tabtitle': tabtitle,
                    'ShiftId': self.shift.shiftId,
                    'token': token,
                    'Ip': info_connection["ip_address"],
                    'NameClinets': info_connection["hostname"],
                    'projectId':projectId,
                    'taskId':taskId,
                }

                try:
                    headers = {
                        "User-Agent": "Your User Agent",  # در صورت نیاز به استفاده از Bearer Token

                    }
                    with open(screenshot_file, 'rb') as file:
                        files = {'CoverFile': file}

                        # ارسال داده‌ها به سرور
                        response = requests.request("POST", url,headers=headers, data=dataActive, files=files, verify=False)

                    if response.status_code == 200:
                        print(f"داده‌ها با موفقیت ارسال شدند: {record_id}")
                        # حذف رکورد از دیتابیس
                        cursor.execute("DELETE FROM reports WHERE id = ?", (record_id,))
                        conn.commit()
                        os.remove(screenshot_file)
                    else:
                        print(response.status_code)
                        print(f"خطا در ارسال داده‌ها: {record_id}")
                        continue  # ادامه پردازش در صورت بروز خطا
                except requests.RequestException as e:
                    print(f"خطا در ارسال داده‌ها: {e}")
                    continue  # ادامه پردازش در صورت بروز خطا
                except Exception as e:
                    print(f"خطا در باز کردن فایل یا حذف آن: {e}")
                    continue  # ادامه پردازش در صورت بروز خطا

            # بستن اتصال به دیتابیس
            conn.close()
            return True
        except Exception as e:
            print(f"Error in send_reports_to_server: {e}")
            return False


class ShiftWorker(QThread):
    shift_started = pyqtSignal(bool)
    shift_ended = pyqtSignal(bool)
    update_status = pyqtSignal(str)
    ShiftId = pyqtSignal(int)
    timeStarted = pyqtSignal(str)

    def __init__(self, action,closed=False,event=None, parent=None):
        super().__init__(parent)
        self.action = action  # 'start' or 'end'
        self.info_connection = get_client_info()
        self.closed = closed
        self.event=event

    def run(self):
        self.update_status.emit("Connecting to server...")

        with open("data.json", "r", encoding='utf-8') as file:
            data = json.load(file)

        host = "https://" + data.get("host")
        with open("login.json", "r", encoding='utf-8') as file:
            login = json.load(file)

        token = login.get("token")
        if self.action == 'start':
            self.start_shift(host, token)
        elif self.action == 'end':
            self.end_shift(host, token)

    def start_shift(self, host, token):
        url = f"{host}/Frogment/Apis/StartShift"
        payload = {'Token': token, "ip": self.info_connection["ip_address"],
                   "NameClinets": self.info_connection["hostname"]}

        try:
            headers = {
                "User-Agent": "Your User Agent",  # در صورت نیاز به استفاده از Bearer Token
                "Content-Type": "application/x-www-form-urlencoded"
            }
            response = requests.request("POST", url,headers=headers, data=payload, verify=False)
            response.raise_for_status()
            response_json = response.json()
            if response_json["status"] == "200":
                with open("shift.json", "w", encoding='utf-8') as file:
                    json.dump(response_json, file, ensure_ascii=False, indent=4)
                self.ShiftId.emit(int(response_json["data"] ))
                self.shift_started.emit(True)
                self.update_status.emit("Shift started successfully")
                self.timeStarted.emit(response_json["started"])
                if self.closed:
                    self.event.accept()
            else:
                self.shift_started.emit(False)
                self.update_status.emit("Failed to start shift")
        except requests.exceptions.HTTPError:
            self.shift_started.emit(False)
            self.update_status.emit("Failed to start shift - HTTP error")
        except Exception:
            self.shift_started.emit(False)
            self.update_status.emit("Failed to start shift - Exception")

    def end_shift(self, host, token):
        endSend=False
        #start send_to_server
        headers = {
            "User-Agent": "Your User Agent",  # در صورت نیاز به استفاده از Bearer Token
            "Content-Type": "application/x-www-form-urlencoded"
        }
        try:

            urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
            self.update_status.emit("Sending reports...")
            # اتصال به دیتابیس
            conn = sqlite3.connect('reports.db')
            cursor = conn.cursor()

            # انتخاب همه رکوردها از جدول reports
            cursor.execute("SELECT * FROM reports")
            records = cursor.fetchall()

            # باز کردن فایل تصویر به صورت باینری
            info_connection = get_client_info()
            with open("data.json", "r", encoding='utf-8') as file:
                data = json.load(file)

            # دریافت فیلد host
            host = "https://" + data.get("host")

            with open("login.json", "r", encoding='utf-8') as file:
                login = json.load(file)

            # دریافت فیلد token
            token = login.get("token")
            url = f"{host}/Frogment/Apis/ReportForShift"

            for record in records:
                record_id, timestamp, screenshot_file, active_project, active_task, mouse_clicks, keyboard_clicks, appname, tabtitle,projectId,taskId = record
                dataActive = {
                    'timestamp': timestamp,
                    'active_project': active_project,
                    'active_task': active_task,
                    'mouse_clicks': mouse_clicks,
                    'keyboard_clicks': keyboard_clicks,
                    'appname': appname,
                    'tabtitle': tabtitle,
                    'ShiftId': self.ShiftId,
                    'token': token,
                    'Ip': info_connection["ip_address"],
                    'NameClinets': info_connection["hostname"],
                    'projectId':projectId,
                    'taskId':taskId,
                }

                try:
                    with open(screenshot_file, 'rb') as file:
                        files = {'CoverFile': file}

                        # ارسال داده‌ها به سرور
                        response = requests.request("POST", url,headers=headers, data=dataActive, files=files, verify=False)

                    if response.status_code == 200:
                        print(f"داده‌ها با موفقیت ارسال شدند: {record_id}")
                        # حذف رکورد از دیتابیس
                        cursor.execute("DELETE FROM reports WHERE id = ?", (record_id,))
                        conn.commit()
                        os.remove(screenshot_file)
                    else:
                        print(f"خطا در ارسال داده‌ها: {record_id}")
                        continue  # ادامه پردازش در صورت بروز خطا
                except requests.RequestException as e:
                    print(f"خطا در ارسال داده‌ها: {e}")
                    continue  # ادامه پردازش در صورت بروز خطا
                except Exception as e:
                    print(f"خطا در باز کردن فایل یا حذف آن: {e}")
                    continue  # ادامه پردازش در صورت بروز خطا

            # بستن اتصال به دیتابیس
            conn.close()
            endSend=True
        except Exception as e:
            print(f"Error in send_reports_to_server: {e}")
            endSend = False

        #end send_reports_to_server
        if endSend:
            self.update_status.emit("Record the end of the shift...")
            url = f"{host}/Frogment/Apis/EndShift"
            payload = {'Token': token, "ip": self.info_connection["ip_address"],
                       "NameClinets": self.info_connection["hostname"]}

            try:

                response = requests.request("POST", url,headers=headers, data=payload, verify=False)
                response.raise_for_status()
                response_json = response.json()
                if response_json["status"] == "200":
                    with open("shift.json", "w", encoding='utf-8') as file:
                        file.write('{"data": 0, "started":""}')
                    self.shift_ended.emit(True)
                    self.update_status.emit("Shift ended successfully")
                    self.ShiftId.emit(0)
                    self.timeStarted.emit("not started")
                else:
                    self.shift_ended.emit(False)
                    self.shift_started.emit(True)
                    self.update_status.emit("Failed to end shift")
            except requests.exceptions.HTTPError:
                self.shift_ended.emit(False)
                self.shift_started.emit(True)
                self.update_status.emit("Failed to end shift - HTTP error")
            except Exception:
                self.shift_ended.emit(False)
                self.shift_started.emit(True)
                self.update_status.emit("Failed to end shift - Exception")
        else:
            self.shift_ended.emit(False)
            self.shift_started.emit(True)
            self.update_status.emit("Failed to end shift - Exception")


class MainDashboard(QMainWindow):
    def __init__(self):
        super().__init__()
        init_db()
        # Set window properties
        user32 = ctypes.windll.user32
        screen_width = user32.GetSystemMetrics(0)
        screen_height = user32.GetSystemMetrics(1)
        left = screen_width - 730
        top = screen_height - 420
        self.setWindowTitle("EM Dashboard")
        self.setGeometry(left, top, 700, 300)
        self.setWindowIcon(QIcon('ixo.png'))

        # Central widget and layout
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout()
        self.central_widget.setLayout(self.layout)

        # Adding Splitter to divide profile and other items
        splitter = QSplitter(Qt.Horizontal)
        self.layout.addWidget(splitter)

        # Profile Widget
        self.profile_widget = ProfileWidget()
        splitter.addWidget(self.profile_widget)

        # Other Items Widget
        other_items_widget = QWidget()
        other_items_layout = QVBoxLayout()
        other_items_widget.setLayout(other_items_layout)
        splitter.addWidget(other_items_widget)

        # Adding ShiftWidget to other items widget
        self.shift_widget = ShiftWidget(self)
        other_items_layout.addWidget(self.shift_widget)

        # Adding menu bar
        self.initMenuBar()

    def initMenuBar(self):
        # Menu bar creation
        menubar = self.menuBar()

        # Adding main menus
        account = menubar.addMenu('Account')
        activities = menubar.addMenu('Activities')
        reports = menubar.addMenu('Reports')
        helpMenu = menubar.addMenu('Help')

        # Adding actions to Account menu
        refreshAction = QAction('Refresh', self)
        refreshAction.triggered.connect(self.refresh)
        viewProfileAction = QAction('View Profile', self)
        viewProfileAction.triggered.connect(self.showProfile)
        logoutAction = QAction('Logout And Close', self)
        logoutAction.triggered.connect(self.logout)

        account.addAction(refreshAction)
        account.addAction(viewProfileAction)
        account.addSeparator()
        account.addAction(logoutAction)

        # Adding actions to Activities menu
        projectsAction = QAction('Projects', self)
        projectsAction.triggered.connect(self.showProject)
        tasksAction = QAction('Tasks', self)
        tasksAction.triggered.connect(self.showTasks)


        activities.addAction(projectsAction)
        activities.addAction(tasksAction)

        # Adding actions to Reports menu
        projectReportAction = QAction('Submitted reports', self)
        projectReportAction.triggered.connect(self.gotoReportMy)
        generalReportAction = QAction('Local Report', self)
        generalReportAction.triggered.connect(self.gotoLocalReport)


        reports.addAction(projectReportAction)
        reports.addAction(generalReportAction)

        # Adding action to Help menu
        helpAction = QAction('Help', self)
        helpAction.triggered.connect(self.show_help)

        helpMenu.addAction(helpAction)

    def closeEvent(self, event):
        try:
            if os.path.exists("shift.json") and os.path.getsize("shift.json") > 0:
                with open("shift.json", "r", encoding='utf-8') as file:
                    content = file.read().strip()
                    if content:
                        shift = json.loads(content)
                        if shift.get("data") != 0:
                            exist = True
                        else:
                            exist = False

            else:
                shift = {}
                exist = False
        except:
            print("Error Read")
            exist = False

        if exist:
            reply = QMessageBox.question(self, 'End of shift confirmation', 'If you want to close the program and finish your shift, select Yes',
                                         QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.Yes:
                self.endShift=ShiftWorker("end",True,event)
                self.endShift.run()

            else:
                event.ignore()
        else:
            reply = QMessageBox.question(self, 'Confirm Exit', 'Are you sure you want to exit?',
                                         QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.Yes:
                event.accept()
            else:
                event.ignore()

    def showProfile(self):
        dialog = DetailDialogProfile()
        dialog.exec_()
    def showProject(self):
        window=ProjectInfo()
        window.show()
    def showTasks(self):
        window=TaskInfo()
        window.show()
    def refresh(self):
        self.shift_widget.update_status("updating...")
        self.shift_widget.setProject()
        self.shift_widget.setTask()
        self.shift_widget.update_status("It was updated")

    def show_error(self, title, message):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Critical)
        msg.setWindowTitle(title)
        msg.setText(message)
        msg.exec_()
    def logout(self):
        try:
            if os.path.exists("shift.json") and os.path.getsize("shift.json") > 0:

                with open("shift.json", "r", encoding='utf-8') as file:
                    print("before : " + file)
                    shift = json.load(file)
                    print(shift)
                    if shift.get("data") != 0:
                        exist = True

            else:
                shift = {}
                exist = False
        except:
            print("Error Read")
            exist = False

        print(exist)

        if exist:
            self.show_error("Error","First, hit the end of your shift, then you can log out of your account")
        else:
            with open("shift.json", "w", encoding='utf-8') as file:
                file.write('{"data": 0, "started":""}')
            with open("login.json", "w", encoding='utf-8') as file:
                file.write('')
            with open("data.json", "w", encoding='utf-8') as file:
                file.write('')
            with open("counts.json", "w", encoding='utf-8') as file:
                file.write('')
            self.close()


    def gotoReportMy(self):
        self.welcome_window = MainReportSend()
        self.welcome_window.show()
    def gotoLocalReport(self):
        self.welcome_window = MainReportLocal()
        self.welcome_window.show()

    def show_help(self):
        import webbrowser
        if os.path.exists("data.json") and os.path.getsize("data.json") > 0:
            with open("data.json", "r", encoding='utf-8') as file:
                data = json.load(file)
                if data.get("host") != "":
                    webbrowser.open_new("https://"+data.get("host")+"/Help/index")

        else:
            # Displaying help message
            QMessageBox.information(self, "Help", "This is the help section.")

    def start_loading(self,loading_screen):
        # ایجاد شیء LoadDataThread و اتصال سیگنال‌ها
        self.load_thread = LoadDataThread(self.shift_widget)
        self.load_thread.finished.connect(loading_screen.close)
        self.load_thread.finished.connect(self.show)
        self.load_thread.start()

class ProfileWidget(QWidget):
    TimeStart="Not Started"
    UserName=""
    def __init__(self):
        super().__init__()
        if os.path.exists("login.json") and os.path.getsize("login.json") > 0:
            with open("login.json", "r", encoding='utf-8') as file:
                login = json.load(file)
                if login.get("data") != "":
                    self.UserName =  login.get("data")
        # Set widget properties
        self.setMinimumWidth(200)
        self.setStyleSheet("background-color: #F0F0F0; border-radius: 10px; padding: 10px;")

        # Main layout
        main_layout = QVBoxLayout(self)
        self.setLayout(main_layout)


        #Profile Layout
        profile_layout = QHBoxLayout()
        main_layout.addLayout(profile_layout)

        UserName_layout = QHBoxLayout()
        main_layout.addLayout(UserName_layout)

        # Load profile picture
        profile_picture = QLabel(self)
        profile_picture.setAlignment(Qt.AlignCenter)
        profile_picture.setPixmap(QPixmap("avatar.png").scaled(150, 150, Qt.KeepAspectRatio, Qt.SmoothTransformation))

        # User name label
        self.username_label = QLabel(self.UserName)
        self.username_label.setAlignment(Qt.AlignCenter)
        self.username_label.setStyleSheet("color: black; font-size:14px;")
        self.username_label.setFont(QFont("Arial", 12))
        profile_layout.addWidget(profile_picture)
        UserName_layout.addWidget(self.username_label)


        # Add profile widgets to profile box
        clickRow_layout = QVBoxLayout()
        clickRow_layout.setAlignment(Qt.AlignTop)
        main_layout.addLayout(clickRow_layout)

        click_layout = QHBoxLayout()
        click_layout.setAlignment(Qt.AlignTop)
        clickRow_layout.addLayout(click_layout)

        self.mouse_label = QLabel("mouse click : 0", self)
        self.keyboard_label = QLabel("keyboard click: 0", self)
        self.mouse_label.setStyleSheet("color: black; font-weight: bold;")
        self.keyboard_label.setStyleSheet("color: black; font-weight: bold;")



        click_layout.addWidget(self.mouse_label)
        click_layout.addWidget(self.keyboard_label)

        #setStart Time Start
        TimeRow_layout = QVBoxLayout()
        TimeRow_layout.setAlignment(Qt.AlignTop)
        main_layout.addLayout(TimeRow_layout)

        timeHor_layout = QHBoxLayout()
        clickRow_layout.addLayout(timeHor_layout)

        self.Start_label = QLabel("Start Time ", self)
        self.Start_Time_label = QLabel(self.TimeStart,self)
        self.Start_label.setStyleSheet("color: black; font-weight: bold;")
        self.Start_Time_label.setStyleSheet("color: black; font-weight: bold;")

        timeHor_layout.addWidget(self.Start_label)
        timeHor_layout.addWidget(self.Start_Time_label)



    def update_counts(self, mouse_clicks, keyboard_clicks):
        self.mouse_label.setText(f'mouse clicks  : {mouse_clicks}')
        self.keyboard_label.setText(f'keyboard clicks : {keyboard_clicks}')
    def update_Time(self, Text):
        self.Start_Time_label.setText(Text)

class ShiftWidget(QWidget):
    # اطلاعات پایه
    shiftId = 0
    stateUser = "Status: Active"
    taskList =[]
    projectList=[]
    timeStarted="not started"

    def __init__(self, parent):
        super().__init__()
        self.parent = parent
        # Set widget properties
        self.setStyleSheet(" ")

        # Main layout
        main_layout = QVBoxLayout(self)
        self.setLayout(main_layout)

        # Project and Task Selection Boxes (50% each)
        project_task_layout = QHBoxLayout()
        project_task_layout.setAlignment(Qt.AlignTop)
        main_layout.addLayout(project_task_layout)

        self.project_combo = QComboBox()
        self.project_combo.addItem("None Project")
        self.project_combo.activated.connect(self.show_project_dialog)

        self.task_combo = QComboBox()
        self.task_combo.addItem("None Task")
        self.task_combo.activated.connect(self.show_task_dialog)

        main_layout.addWidget(self.project_combo)
        main_layout.addWidget(self.task_combo)



        # End time widgets
        self.button = QPushButton("Submit a report")
        self.button.clicked.connect(self.SendReport)
        self.button.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        main_layout.addWidget(self.button)



        self.online_label = QLabel(self.stateUser)
        self.online_label.setAlignment(Qt.AlignCenter)
        self.online_label.setStyleSheet("  font-weight: bold;font-size:14px")
        main_layout.addWidget(self.online_label)
        # Shift control buttons
        control_layout = QHBoxLayout()
        control_layout.setAlignment(Qt.AlignTop)
        main_layout.addLayout(control_layout)

        self.start_button = QPushButton("Start Shift")
        self.end_button = QPushButton("End Shift")
        self.end_button.setEnabled(False)

        # Set button styles
        self.start_button.setStyleSheet(
            "font-size: 14px; background-color: lightgreen; border: 2px solid green; border-radius: 5px; padding: 5px;")
        self.end_button.setStyleSheet(
            "font-size: 14px; background-color: salmon; border: 2px solid red; border-radius: 5px; padding: 5px;")

        control_layout.addWidget(self.start_button)
        control_layout.addWidget(self.end_button)

        # Connect button signals
        self.start_button.clicked.connect(self.start_shift)
        self.end_button.clicked.connect(self.end_shift)

        self.shift_thread = ShiftThread()
        self.shift_thread.count_updated.connect(self.update_counts)
        minutes = 2
        if os.path.exists("login.json") and os.path.getsize("login.json") > 0:
            with open("login.json", "r", encoding='utf-8') as file:
                login = json.load(file)
                if login.get("timer") != 0:
                    minutes = int(login.get("timer"))

        self.seconds = minutes * 60
        self.screenshot_thread = ScreenshotThread(interval=self.seconds, shift_widget=self)
        self.checkShift()
        # تعریف نمونه `ReportThread`
        self.report_thread = ReportThread(self)
        self.report_thread.finished.connect(self.on_report_finished)





    def checkShift(self):
        exist = False

        if os.path.exists("shift.json") and os.path.getsize("shift.json") > 0:
            with open("shift.json", "r", encoding='utf-8') as file:
                shift = json.load(file)
                if shift.get("data") != 0:
                    exist = True
        else:
            shift = {}
            exist = False

        if os.path.exists("counts.json") and os.path.getsize("counts.json") > 0:
            with open("counts.json", "r", encoding='utf-8') as file:
                content = file.read()
                if content:
                    clicks = json.loads(content)
                else:
                    clicks = {}
        else:
            clicks = {}

        if exist:
            self.shiftId = shift.get("data")
            print(shift.get("data"))
            print(self.shiftId)
            self.parent.profile_widget.update_Time(shift.get("started"))

            self.parent.profile_widget.update_counts(clicks.get("mouse_clicks"), clicks.get("keyboard_clicks"))

            self.start_button.setEnabled(False)
            self.end_button.setEnabled(True)
            # Get current date/time and update start time label


            self.shift_thread.start()
            self.screenshot_thread.start()
            self.stateUser = "They are on shift"
            self.online_label.setText("They are on shift")
        else:
            self.stateUser = "Waiting for the start of the shift..."
            self.online_label.setText("Waiting for the start of the shift...")
        try:
            self.setProject()
        except:
            print("Error")
        try:
            self.setTask()
        except:
            print("Error")

    def SendReport(self):
        if   len(self.taskList)>0 and len(self.projectList)>0:
            if self.shiftId!=0 :
                dialog = ReportDialog(self.projectList,self.taskList,self.shiftId,self.project_combo.currentIndex(),self.task_combo.currentIndex())
                if dialog.exec_() == QDialog.Accepted:
                    # Process the accepted data here
                    pass
            else:
                self.update_status("Start your shift first, then submit a report")
        else:
            self.update_status("No project or task has been specified for you")
    def setTask(self):
        with open("data.json", "r", encoding='utf-8') as file:
            data = json.load(file)

        host = "https://" + data.get("host")
        with open("login.json", "r", encoding='utf-8') as file:
            login = json.load(file)

        token = login.get("token")
        url = f"{host}/Frogment/Apis/GetTask"
        payload = {'Token': token, "ip": "",   "NameClinets": ""}
        headers = {
            "User-Agent": "Your User Agent",  # در صورت نیاز به استفاده از Bearer Token
            "Content-Type": "application/x-www-form-urlencoded"
        }
        try:
            response = requests.request("POST", url,headers=headers, data=payload, verify=False)
            response.raise_for_status()
            if response.status_code == 200:
                self.taskList = response.json()
                if len(self.taskList)>0:
                    model = QStandardItemModel()
                    for item in self.taskList:
                        standard_item = QStandardItem(item["title"])
                        standard_item.setData(item["id"], Qt.UserRole)
                        model.appendRow(standard_item)
                    self.task_combo.setModel(model)
                else:
                    model = QStandardItemModel()
                    standard_item = QStandardItem("Unspecified task")
                    standard_item.setData(0, Qt.UserRole)
                    model.appendRow(standard_item)
                    self.task_combo.setModel(model)
                    print("none selected")
                return True
            else:
                print("Failed to Get Task")
                self.show_error("Internet error",
                                "Please check your internet so we can get a list of your projects and tasks")
                return False
        except requests.exceptions.HTTPError:
            self.show_error("Internet error",
                            "Please check your internet so we can get a list of your projects and tasks")
            return False
        except Exception:
            self.show_error("Internet error",
                            "Please check your internet so we can get a list of your projects and tasks")
            return False
        #self.task_combo.addItem("Active Task: Task XYZ")

    def setProject(self):
        with open("data.json", "r", encoding='utf-8') as file:
            data = json.load(file)

        host = "https://" + data.get("host")
        with open("login.json", "r", encoding='utf-8') as file:
            login = json.load(file)

        token = login.get("token")
        url = f"{host}/Frogment/Apis/GetProject"
        payload = {'Token': token, "ip": "", "NameClinets": ""}
        headers = {
            "User-Agent": "Your User Agent",  # در صورت نیاز به استفاده از Bearer Token
            "Content-Type": "application/x-www-form-urlencoded"
        }
        try:
            response = requests.request("POST", url,headers=headers, data=payload, verify=False)
            response.raise_for_status()
            if response.status_code == 200:
                self.projectList = response.json()

                if len( self.projectList)>0:
                    models = QStandardItemModel()
                    for item in self.projectList:
                        standard_item = QStandardItem(item["project"]["title"])
                        standard_item.setData(item["projectId"], Qt.UserRole)
                        models.appendRow(standard_item)
                    self.project_combo.setModel(models)
                else:
                    models = QStandardItemModel()
                    standard_item = QStandardItem("An unspecified project")
                    standard_item.setData(0, Qt.UserRole)
                    models.appendRow(standard_item)
                    self.project_combo.setModel(models)
                return  True
            else:
                self.show_error("Internet error",
                                "Please check your internet so we can get a list of your projects and tasks")
                return False

        except requests.exceptions.HTTPError:
            self.show_error("Internet error",
                            "Please check your internet so we can get a list of your projects and tasks")
            return False
        except Exception:
            self.show_error("Internet error",
                            "Please check your internet so we can get a list of your projects and tasks")
            return False
        # self.task_combo.addItem("Active Task: Task XYZ")

    def show_error(self, title, message):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Critical)
        msg.setWindowTitle(title)
        msg.setText(message)
        msg.exec_()

    def show_Succ(self, title, message):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Information)
        msg.setWindowTitle(title)
        msg.setText(message)
        msg.exec_()

    def show_project_dialog(self, index):
        dialog = QDialog(self)
        dialog.setWindowTitle("Select Active Project")
        dialog.setMinimumSize(300, 100)

        combo_box = QComboBox(dialog)
        combo_box.addItem("Project: None")
        combo_box.move(20, 20)

        # Data for Project
        project_model = QStandardItemModel()
        for item in self.projectList:
            standard_item = QStandardItem(item["project"]["title"])
            standard_item.setData(item["projectId"], Qt.UserRole)
            project_model.appendRow(standard_item)
        combo_box.setModel(project_model)



        confirm_button = QPushButton("Confirm", dialog)
        confirm_button.move(200, 20)
        confirm_button.clicked.connect(dialog.accept)

        dialog.exec_()
        if dialog.result() == QDialog.Accepted:
            self.project_combo.setCurrentIndex(index)

    def show_task_dialog(self, index):
        dialog = QDialog(self)
        dialog.setWindowTitle("Select Active Task")
        dialog.setMinimumSize(300, 100)

        combo_box = QComboBox(dialog)
        combo_box.addItem("Task: None")
        combo_box.move(20, 20)

        # Data for Task
        task_model = QStandardItemModel()
        for item in self.taskList:
            standard_item = QStandardItem(item["title"])
            standard_item.setData(item["id"], Qt.UserRole)
            task_model.appendRow(standard_item)
        combo_box.setModel(task_model)

        confirm_button = QPushButton("Confirm", dialog)
        confirm_button.move(200, 20)
        confirm_button.clicked.connect(dialog.accept)

        dialog.exec_()
        if dialog.result() == QDialog.Accepted:
            self.task_combo.setCurrentIndex(index)

    def start_shift(self):
        self.start_button.setEnabled(False)  # غیرفعال کردن دکمه شروع شیفت
        self.shift_worker = ShiftWorker('start')
        self.shift_worker.shift_started.connect(self.on_shift_started)
        self.shift_worker.update_status.connect(self.update_status)
        self.shift_worker.ShiftId.connect(self.update_shiftId)
        self.shift_worker.timeStarted.connect(self.update_timeStarted)
        self.shift_worker.start()
        self.online_label.setText("Starting shift...")

    def end_shift(self):
        print("Ending shift")
        self.end_button.setEnabled(False)  # غیرفعال کردن دکمه پایان شیفت
        self.online_label.setText("Ending shift...")
        self.shift_worker = ShiftWorker('end')
        self.shift_worker.shift_ended.connect(self.on_shift_ended)
        self.shift_worker.update_status.connect(self.update_status)
        self.shift_worker.ShiftId.connect(self.update_shiftId)
        self.shift_worker.timeStarted.connect(self.update_timeStarted)

        self.shift_worker.start()



    def on_shift_started(self, success):

        if success:
            self.start_button.setEnabled(False)  # دکمه شروع شیفت غیرفعال باقی می‌ماند
            self.end_button.setEnabled(True)
            self.shift_thread.start()
            self.screenshot_thread=ScreenshotThread(interval=self.seconds,shift_widget=self)
            self.screenshot_thread.start()
        else:
            self.start_button.setEnabled(True)  # دکمه شروع شیفت دوباره فعال می‌شود
            self.online_label.setText("Failed to start shift")
            self.end_button.setEnabled(False)

    def on_shift_ended(self, success):
        if success:
            self.start_button.setEnabled(True)
            self.end_button.setEnabled(False)
            self.shift_thread.mouse_clicks=0
            self.shift_thread.keyboard_clicks=0
            self.update_counts(0, 0)
            self.shift_thread.stop()
            self.screenshot_thread.stop()
        else:
            self.start_button.setEnabled(False)
            self.end_button.setEnabled(True)
            self.online_label.setText("Failed to end shift")

    def update_status(self, status):
        self.online_label.setText(status)

    def update_shiftId(self, shiftId):
        self.shiftId =shiftId

    def update_timeStarted(self, timerStarted):
        self.parent.profile_widget.update_Time(timerStarted)
    def on_report_finished(self, result):
        if result:
            print("گزارش‌ها با موفقیت ارسال شدند.")
        else:
            print("خطا در ارسال گزارش‌ها.")

    def update_counts(self, mouse_clicks, keyboard_clicks):
        self.parent.profile_widget.update_counts(mouse_clicks, keyboard_clicks)
        self.save_counts()

    def save_counts(self):
        counts = {
            'mouse_clicks': self.shift_thread.mouse_clicks,
            'keyboard_clicks': self.shift_thread.keyboard_clicks
        }
        with open('counts.json', 'w') as file:
            json.dump(counts, file)


def get_client_info():
    # Get the hostname
    hostname = socket.gethostname()

    # Get the IP address
    ip_address = socket.gethostbyname(hostname)
    print(ip_address)
    print(hostname)
    # Create a dictionary with the information
    client_info = {
        "hostname": hostname,
        "ip_address": ip_address
    }

    return client_info
class ReportDialog(QDialog):
    def __init__(self, modelProject, modelTask, ShiftId,indexProject,indexTask):
        super().__init__()
        print(modelProject)
        print(modelTask)
        print(ShiftId)
        self.setWindowTitle("Report Submission")
        self.setMinimumSize(400, 300)

        layout = QVBoxLayout()

        # Title
        self.title_label = QLabel("Select Active Project and Task")
        layout.addWidget(self.title_label)

        # Project Combo Box
        self.project_combo = QComboBox()
        self.project_combo.addItem("Project: None")
        layout.addWidget(self.project_combo)

        # Task Combo Box
        self.task_combo = QComboBox()
        self.task_combo.addItem("Task: None")
        layout.addWidget(self.task_combo)

        # Data for Project
        project_model = QStandardItemModel()
        for item in modelProject:
            standard_item = QStandardItem(item["project"]["title"])
            standard_item.setData(item["projectId"], Qt.UserRole)
            project_model.appendRow(standard_item)
        self.project_combo.setModel(project_model)

        # Data for Task
        task_model = QStandardItemModel()
        for item in modelTask:
            standard_item = QStandardItem(item["title"])
            standard_item.setData(item["id"], Qt.UserRole)
            task_model.appendRow(standard_item)
        self.task_combo.setModel(task_model)

        # Text input for report
        self.report_input = QTextEdit()
        self.report_input.setPlaceholderText("Enter your report here...")
        layout.addWidget(self.report_input)

        # Confirm Button
        confirm_button = QPushButton("Submit Report")
        confirm_button.clicked.connect(self.submit_report)
        layout.addWidget(confirm_button)
        self.project_combo.setCurrentIndex(indexProject)
        self.task_combo.setCurrentIndex(indexTask)
        self.setLayout(layout)

    def submit_report(self):
        selected_project_index = self.project_combo.currentIndex()
        selected_task_index = self.task_combo.currentIndex()

        selected_project_id = self.project_combo.itemData(selected_project_index, Qt.UserRole)
        selected_task_id = self.task_combo.itemData(selected_task_index, Qt.UserRole)

        report_text = self.report_input.toPlainText()

        # Here you can add the code to process the report
        print(f"Project ID: {selected_project_id}")
        print(f"Task ID: {selected_task_id}")
        print(f"Report: {report_text}")
        self.title_label.setText("Wait Sending...")
        with open("data.json", "r", encoding='utf-8') as file:
            data = json.load(file)

        # دریافت فیلد host
        host = "https://" + data.get("host")

        with open("login.json", "r", encoding='utf-8') as file:
            login = json.load(file)

        # دریافت فیلد token
        token = login.get("token")
        url = f"{host}/Frogment/Apis/SetTextReport"

        dataActive = {
            'ProjectId': selected_project_id,
            'TaskId': selected_task_id,
            'Text': report_text,
            'Token':token
        }

        try:
            headers = {
                "User-Agent": "Your User Agent",  # در صورت نیاز به استفاده از Bearer Token
                "Content-Type": "application/x-www-form-urlencoded"
            }
            # ارسال داده‌ها به سرور
            response = requests.request("POST", url,headers=headers, data=dataActive, verify=False)

            if response.status_code == 200:
                response_json = response.json()
                if(response_json["status"]=="200"):
                    self.title_label.setText("Submitted successfully")
                    self.accept()
                else:
                    self.title_label.setText(response_json["results"])


            else:
                self.title_label.setText("Error sending, please try again")

        except requests.RequestException as e:
            self.title_label.setText("Error sending, please try again")

        except Exception as e:
            self.title_label.setText("Error sending, please try again")
        # Close the dialog

class DetailDialogProfile(QDialog):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("EM Profile")
        user32 = ctypes.windll.user32
        screen_width = user32.GetSystemMetrics(0)
        screen_height = user32.GetSystemMetrics(1)
        left = screen_width - 730
        top = screen_height - 420
        self.setGeometry(left, top, 400, 400)
        self.setWindowIcon(QIcon('ixo.png'))

        layout = QVBoxLayout()
        with open("login.json", "r", encoding='utf-8') as file:
            login = json.load(file)
        exist=False
        if os.path.exists("shift.json") and os.path.getsize("shift.json") > 0:
            with open("shift.json", "r", encoding='utf-8') as file:
                shift = json.load(file)
                if shift.get("data") != 0:
                    exist = True
        else:
            shift = {}
            exist = False
        label_shift=""
        if exist:
            label_shift="in shift"
        else:
            label_shift = "He has not entered the shift yet"
        token = login.get("token")
        email = login.get("data")
        accessClinetSendReport = login.get("accessClinetSendReport")
        profile_picture = QLabel(self)
        profile_picture.setAlignment(Qt.AlignCenter)
        profile_picture.setPixmap(QPixmap("avatar.png").scaled(150, 150, Qt.KeepAspectRatio, Qt.SmoothTransformation))

        title_label = QLabel(f"Email : {email}")
        title_label.setStyleSheet("font-size:18px")
        stateShift = QLabel(f"Shift status : {label_shift}")
        stateShift.setStyleSheet("font-size:15px")
        caption_label = QLabel(f"Token: {token}")
        caption_label.setStyleSheet("font-size:15px")
        create_time_label = QLabel(f"Access Send Report: {accessClinetSendReport}")
        create_time_label.setStyleSheet("font-size:15px")

        layout.addWidget(profile_picture)
        layout.addWidget(title_label)
        layout.addWidget(stateShift)
        layout.addWidget(caption_label)

        layout.addWidget(create_time_label)

        self.setLayout(layout)

class LoadingScreen(QDialog):
    def __init__(self):
        super().__init__()
        user32 = ctypes.windll.user32
        screen_width = user32.GetSystemMetrics(0)
        screen_height = user32.GetSystemMetrics(1)
        left = screen_width - 300
        top = screen_height - 250
        self.setWindowTitle("EM Loading")
        self.setGeometry(left, top, 200, 100)
        self.setWindowIcon(QIcon('ixo.png'))
        self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.CustomizeWindowHint)
        layout = QVBoxLayout()
        self.label = QLabel("Loading, please wait...")
        layout.addWidget(self.label)
        self.setLayout(layout)



class LoadDataThread(QThread):
    finished = pyqtSignal(bool)  # سیگنال برای اتمام عملیات

    def __init__(self, shift_widget):
        super().__init__()
        self.shift_widget = shift_widget

    def run(self):
        try:
            self.shift_widget.setProject()
            self.shift_widget.setTask()
        except Exception as e:
            print(f"Error loading data: {e}")
        self.finished.emit(True)



