import tkinter as tk
from tkinter import ttk, messagebox
from PIL import Image, ImageTk
from dotenv import load_dotenv
import mysql.connector
import threading
import datetime
import pyautogui
import platform
import socket
import subprocess
import time
import os
import ctypes

load_dotenv()

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
IS_WINDOWS = platform.system() == "Windows"
IS_LINUX = platform.system() == "Linux"

class KioskMode:
    def __init__(self, root):
        self.root = root
        self.blocker = None
        self.is_windows = IS_WINDOWS
        self.is_linux = IS_LINUX

    def activate(self):
        self.root.attributes('-fullscreen', True)
        self.root.attributes('-topmost', True)
        self.root.protocol("WM_DELETE_WINDOW", lambda: None)
        self.root.bind("<Alt-F4>", lambda e: "break")
        self.root.bind("<Control-Escape>", lambda e: "break")

        self.blocker = tk.Toplevel(self.root)
        self.blocker.attributes('-fullscreen', True)
        self.blocker.attributes('-topmost', True)
        self.blocker.attributes('-alpha', 0.0)
        self.blocker.overrideredirect(True)
        self.blocker.config(cursor="none")
        self.blocker.lift()

        if self.is_windows:
            self._disable_task_switching_windows()
        elif self.is_linux:
            self._disable_alt_tab_linux()

    def deactivate(self):
        if self.blocker:
            self.blocker.destroy()
            self.blocker = None
        if self.is_windows:
            self._enable_task_switching_windows()
        elif self.is_linux:
            self._enable_alt_tab_linux()

    def _disable_task_switching_windows(self):
        try:
            ctypes.windll.user32.BlockInput(True)
        except Exception as e:
            print(f"Windows kiosk mode limited: {e}")

    def _enable_task_switching_windows(self):
        try:
            ctypes.windll.user32.BlockInput(False)
        except Exception as e:
            print(f"Failed to re-enable input: {e}")

    def _disable_alt_tab_linux(self):
        try:
            subprocess.call(["gsettings", "set", "org.gnome.desktop.wm.keybindings", "switch-applications", "[]"])
            subprocess.call(["gsettings", "set", "org.gnome.desktop.wm.keybindings", "switch-windows", "[]"])
            subprocess.call(["gsettings", "set", "org.gnome.desktop.wm.keybindings", "panel-main-menu", "[]"])
        except Exception as e:
            print(f"Linux kiosk mode limited: {e}")

    def _enable_alt_tab_linux(self):
        try:
            subprocess.call(["gsettings", "reset", "org.gnome.desktop.wm.keybindings", "switch-applications"])
            subprocess.call(["gsettings", "reset", "org.gnome.desktop.wm.keybindings", "switch-windows"])
            subprocess.call(["gsettings", "reset", "org.gnome.desktop.wm.keybindings", "panel-main-menu"])
        except Exception as e:
            print(f"Failed to restore Linux keybindings: {e}")

def screenshot_service(emp_id, error_callback):
    def get_active_window():
        try:
            if IS_WINDOWS:
                import pygetwindow as gw
                active_window = gw.getActiveWindow()
                return active_window.title if active_window else "Unknown"
            elif IS_LINUX:
                try:
                    win_id = subprocess.check_output(["xdotool", "getactivewindow"]).strip()
                    win_name = subprocess.check_output(["xdotool", "getwindowname", win_id]).strip()
                    return win_name.decode("utf-8")
                except Exception:
                    # fallback to Wnck
                    import gi
                    gi.require_version('Wnck', '3.0')
                    from gi.repository import Wnck, Gtk

                    Gtk.init([])
                    screen = Wnck.Screen.get_default()
                    screen.force_update()
                    active_window = screen.get_active_window()
                    if active_window:
                        name = active_window.get_name()
                        return name if name else "Unknown"
                    return "Unknown"
        except Exception as e:
            return f"Unknown (error: {e})"

    device_name = socket.gethostname()

    while True:
        try:
            timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            folder = os.path.join(os.getcwd(), "screenshots")
            os.makedirs(folder, exist_ok=True)
            filename = os.path.join(folder, f"{device_name}-screenshot_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.png")
            screenshot = pyautogui.screenshot()
            screenshot.save(filename)
            active_app = get_active_window()

            ssl_params = {"ssl_disabled": True} if IS_WINDOWS else {"ssl_ca": "do-ca.crt"}

            conn = mysql.connector.connect(
                host=os.getenv("DB_HOST"),
                port=int(os.getenv("DB_PORT")),
                user=os.getenv("DB_USER"),
                password=os.getenv("DB_PASSWORD"),
                database=os.getenv("DB_NAME"),
                **ssl_params
            )
            cursor = conn.cursor()
            cursor.execute("""
                INSERT INTO employee_screenshot (emp_id, device, app, filename, timestamp)
                VALUES (%s, %s, %s, %s, %s)
            """, (emp_id, device_name, active_app, os.path.basename(filename), timestamp))
            conn.commit()
            cursor.close()
            conn.close()
        except Exception as e:
            error_callback(f"Screenshot service error: {e}")

        time.sleep(600)

def authenticate_user(username, password, error_callback):
    try:
        ssl_params = {"ssl_disabled": True} if IS_WINDOWS else {"ssl_ca": "do-ca.crt"}

        conn = mysql.connector.connect(
            host=os.getenv("DB_HOST"),
            port=int(os.getenv("DB_PORT")),
            user=os.getenv("DB_USER"),
            password=os.getenv("DB_PASSWORD"),
            database=os.getenv("DB_NAME"),
            **ssl_params
        )
        cursor = conn.cursor(dictionary=True)
        cursor.execute("SELECT * FROM employee WHERE email=%s AND password=%s", (username, password))
        result = cursor.fetchone()
        conn.close()
        return result
    except mysql.connector.Error as err:
        error_callback(f"Database error: {err}")
        return None

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Akash")
        self.kiosk = KioskMode(self)
        self.kiosk.activate()
        self.login_frame = LoginFrame(self)
        self.dashboard_frame = None
        self.login_frame.pack(fill='both', expand=True)

    def show_dashboard(self, user_data):
        self.kiosk.deactivate()
        self.login_frame.pack_forget()
        self.dashboard_frame = DashboardFrame(self, user_data)
        self.dashboard_frame.start_background_thread()
        self.withdraw()

class LoginFrame(tk.Frame):
    def __init__(self, master):
        super().__init__(master)
        try:
            bg_img = Image.open(os.path.join(BASE_DIR, "login.png"))
            self.bg = ImageTk.PhotoImage(bg_img.resize((master.winfo_screenwidth(), master.winfo_screenheight())))
        except Exception as e:
            messagebox.showerror("Error", f"Login background image load error: {e}")
            self.bg = None

        if self.bg:
            bg_label = tk.Label(self, image=self.bg)
            bg_label.place(x=0, y=0, relwidth=1, relheight=1)

        panel = tk.Frame(self, bg='white', bd=2, relief="ridge")
        panel.place(relx=0.98, rely=0.5, anchor='e', width=350, height=350)

        tk.Label(panel, text="Akash", font=("Trebuchet MS", 20, "bold"), fg="#0a84ff", bg="white").pack(pady=(10, 0))
        tk.Label(panel, text="Username:", bg="white", font=("Helvetica", 12, "bold")).pack(pady=(10, 5))
        self.username_entry = ttk.Entry(panel, font=("Helvetica", 12), width=30)
        self.username_entry.pack(pady=5)

        tk.Label(panel, text="Password:", bg="white", font=("Helvetica", 12, "bold")).pack(pady=(10, 5))
        password_frame = tk.Frame(panel, bg="white")
        password_frame.pack(pady=5)

        self.password_var = tk.StringVar()
        self.password_entry = ttk.Entry(password_frame, textvariable=self.password_var, show="*", font=("Helvetica", 12), width=24)
        self.password_entry.pack(side="left", padx=(0, 5))

        try:
            self.eye_open = ImageTk.PhotoImage(Image.open(os.path.join(BASE_DIR, "eye.png")).resize((20, 20)))
            self.eye_closed = ImageTk.PhotoImage(Image.open(os.path.join(BASE_DIR, "eye_off.png")).resize((20, 20)))
        except Exception as e:
            messagebox.showerror("Error", f"Eye icons error: {e}")
            self.eye_open = self.eye_closed = None

        self.eye_visible = False
        self.eye_button = tk.Button(password_frame, image=self.eye_closed, command=self.toggle_password, relief="flat", bg="white", bd=0)
        self.eye_button.pack(side="left")

        ttk.Button(panel, text="Login", command=self.login).pack(pady=10)

    def toggle_password(self):
        self.eye_visible = not self.eye_visible
        if self.eye_visible:
            self.password_entry.config(show="")
            self.eye_button.config(image=self.eye_open)
        else:
            self.password_entry.config(show="*")
            self.eye_button.config(image=self.eye_closed)

    def login(self):
        username = self.username_entry.get()
        password = self.password_var.get()
        if username and password:
            user_data = authenticate_user(username, password, self.show_error)
            if user_data:
                self.master.show_dashboard(user_data)
            else:
                messagebox.showerror("Login Failed", "Invalid credentials")
        else:
            messagebox.showerror("Input Error", "Username and password cannot be empty")

    def show_error(self, message):
        messagebox.showerror("Error", message)

class DashboardFrame(tk.Frame):
    def __init__(self, master, user_data):
        super().__init__(master)
        self.user_data = user_data

        try:
            bg_img = Image.open(os.path.join(BASE_DIR, "dashboard.png"))
            self.bg = ImageTk.PhotoImage(bg_img.resize((master.winfo_screenwidth(), master.winfo_screenheight())))
        except Exception as e:
            messagebox.showerror("Error", f"Dashboard background load error: {e}")
            self.bg = None

        if self.bg:
            tk.Label(self, image=self.bg).place(x=0, y=0, relwidth=1, relheight=1)

        tk.Label(self, text=f"Welcome, {user_data['name']}", font=("Trebuchet MS", 24, "bold"), fg="#0a84ff", bg="white").pack(pady=20)
        ttk.Button(self, text="Logout", command=self.logout).pack(pady=10)

    def start_background_thread(self):
        emp_id = self.user_data['emp_id']
        t = threading.Thread(target=screenshot_service, args=(emp_id, self.show_error), daemon=True)
        t.start()

    def logout(self):
        self.pack_forget()
        self.master.login_frame.pack(fill='both', expand=True)
        self.master.kiosk.activate()

    def show_error(self, message):
        messagebox.showerror("Error", message)

if __name__ == "__main__":
    app = App()
    app.mainloop()
