import os
import tkinter as tk
import pyperclip
import threading
import keyboard
import requests
import base64
from io import BytesIO
from PIL import ImageGrab
import pyautogui   # 🚀 NAYI LIBRARY ()
import time        # 🚀 NAYI LIBRARY (Delay ke liye)
import random     
import mss
from PIL import Image
import uiautomation as auto  # 🚀 NEW LIBRARY (UI Text Extract ke liye)
import pythoncom

import ctypes
from ctypes import wintypes, POINTER, c_void_p, byref
import comtypes.client


comtypes.client.GetModule('oleacc.dll')

IID_IServiceProvider = comtypes.GUID("{6D5140C1-7436-11CE-8034-00AA006009FA}")
IID_IAccessible2 = comtypes.GUID("{E89F726E-C4F4-4C19-BB19-B647D7FA8478}")

oleacc = ctypes.windll.oleacc


# APNA VERCEL LINK YAHAN DALO
VERCEL_API_URL = 'https://iq-overlay-pointer.vercel.app/api'

# Session reusable connection ke liye
session = requests.Session()

class IQPointer:
    def __init__(self):
        self.root = tk.Tk()
        self.root.attributes('-topmost', True)
        self.root.overrideredirect(True)
        self.root.attributes('-transparentcolor', 'white')
        self.root.config(bg='white')

        # Stealth Label
        self.label = tk.Label(self.root, text=".", font=('Consolas', 8, 'bold'), 
                            fg='#d3d3d3', bg='white', wraplength=350, justify="left")
        self.label.pack()

        # 🚀 NAYA: Secret Code Preview Window (ULTRA GHOST MODE)
        self.code_window = tk.Toplevel(self.root)
        self.code_window.attributes('-topmost', True)
        self.code_window.overrideredirect(True)
        
        # Background gayab (Transparent)
        self.code_window.attributes('-transparentcolor', 'white')
        
        
        self.code_window.attributes('-alpha', 0.75) 
        self.code_window.withdraw() 
        
        
        self.code_text = tk.Text(self.code_window, font=('Consolas', 8, 'bold'), bg='white', fg='#d3d3d3', 
                                 width=55, height=20, relief='flat', highlightthickness=0,
                                 insertbackground='white')
        self.code_text.pack()
        self.is_code_visible = False


        self.last_text = pyperclip.paste()
        self.is_hidden = False 
        self.is_processing = False #  Lock rakha hai taaki 429 error (Spam) na aaye

        #  NAYA: Sniper Box (Area Scan) ke variables
        self.snip_step = 0
        self.snip_step_deep = 0  #  NAYA: F9 ke liye
        self.snip_step_ia2 = 0  #  NAYA: F10 ke liye
        self.snip_x1 = 0
        self.snip_y1 = 0

        #  NAYE VARIABLES: Pause/Resume ke liye
        self.is_typing = False
        self.is_paused = False
        self.text_to_type = ""
        self.type_index = 0

        # 🚀 NAYE VARIABLES: (Mash-to-Type) ke liye
        self.mash_text = ""
        self.mash_index = 0
        self.mash_hook = None

        # 🚀 NAYE VARIABLES: Merge Mode ke liye
        self.is_merge_mode = False
        self.merge_buffer = ""
        
        # --- HOTKEYS ---
        keyboard.add_hotkey('ctrl+c', self.trigger_api)
        keyboard.add_hotkey('esc', self.stealth_hide)
        keyboard.add_hotkey('1+`', self.stealth_show)
        keyboard.add_hotkey('ctrl+q', self.panic_exit)
        keyboard.add_hotkey('ctrl+v', self.auto_hide)
        keyboard.add_hotkey('alt+s', self.screen_read_trigger) # Scan
        keyboard.add_hotkey('ctrl+shift', self.retry_api)              # Retry
        keyboard.add_hotkey('alt+v', self.force_paste)         #  Auto-Typer 
        keyboard.add_hotkey('alt+x', self.toggle_code_view)    #  Dekhne ke liye
        #  NAYA: Stealth Scroll ke hotkeys
        keyboard.add_hotkey('alt+up', self.scroll_up)          # Upar scroll karne ke liye
        keyboard.add_hotkey('alt+down', self.scroll_down)      # Neeche scroll karne ke liye
        keyboard.add_hotkey('f10', self.extract_text_by_area)
        keyboard.add_hotkey('f9', self.extract_text_by_area_deep)

        keyboard.add_hotkey('f8', self.extract_text_by_area_ia2)
        keyboard.add_hotkey('alt+c', self.toggle_merge_mode)


        # "Alt + M" 
        keyboard.add_hotkey('alt+m', self.start_mash_mode)


        
        self.current_mode = "dsa"  # Default 
        
        keyboard.add_hotkey('alt+1', lambda: self.change_mode("aptitude"))
        keyboard.add_hotkey('alt+2', lambda: self.change_mode("dsa"))
        keyboard.add_hotkey('alt+3', lambda: self.change_mode("fullstack"))
        keyboard.add_hotkey('alt+4', lambda: self.change_mode("aws"))
        keyboard.add_hotkey('alt+5', lambda: self.change_mode("ocr")) 
        
        self.update_ui()
        self.monitor_loop()
        self.root.mainloop()


       
    def change_mode(self, mode):
        self.current_mode = mode
        if mode == "aptitude":
            self.label.config(fg="#d3d3d3", text="ap")  
        elif mode == "dsa":
            self.label.config(fg="#d3d3d3", text="dsa")  
        elif mode == "fullstack":
            self.label.config(fg="#d3d3d3", text="fu")  
        elif mode == "aws":
            self.label.config(fg="#d3d3d3", text="aw")  
        elif mode == "ocr":
            self.label.config(fg="#d3d3d3", text="cp")  

        # 1 second baad wapas stealth dot (.) ban jayega
        self.root.after(1000, lambda: self.label.config(text="."))

    def retry_api(self):
        """Manually trigger last copied text again"""
        #  NAYA LOCK: Agar Auto-typing ya Mash mode chal raha hai, toh ignore karo!
        if self.is_typing or getattr(self, 'mash_hook', None):
            return

        current_text = pyperclip.paste()
        if len(current_text.strip()) > 5:
            self.label.config(text="re..")
            #  FIX 1: Yahan se self.last_text = "" hata diya taaki double loop trigger na ho
            threading.Thread(target=self.get_ai_answer, args=(current_text,), daemon=True).start()

    #  STEP 1: Invisible Box ke Coordinates (X, Y) set karna
    def extract_text_by_area(self):
        if self.is_hidden or self.is_processing:
            return

        if self.snip_step == 0:
            # Pera Click (Top-Left corner)
            self.snip_x1, self.snip_y1 = pyautogui.position()
            self.snip_step = 1
            self.label.config(text="..") # Tool bata raha hai ki pehla point lock ho gaya
        else:
            # Dusra Click (Bottom-Right corner)
            x2, y2 = pyautogui.position()
            self.snip_step = 0
            self.label.config(text="..")
            
            # Box ki boundary fix karo (Chahe mouse ulta bhi chalaya ho)
            left = min(self.snip_x1, x2)
            right = max(self.snip_x1, x2)
            top = min(self.snip_y1, y2)
            bottom = max(self.snip_y1, y2)
            
            # Scan chalu karo background mein
            threading.Thread(target=self.process_area_extraction, args=(left, right, top, bottom), daemon=True).start()

    # 🚀 STEP 2: Us Area ke andar ka Text nikalna
    def process_area_extraction(self, left, right, top, bottom):
        try:
            pythoncom.CoInitialize()
            self.is_processing = True
            
            # Mouse ki jagah se Main Window pakdo
            main_app = auto.ControlFromPoint(int(left), int(top)).GetTopLevelControl()
            
            full_text = ""
            
            # Pura app scan karo
            for item, depth in auto.WalkControl(main_app, maxDepth=8):
                try:
                    rect = item.BoundingRectangle
                    # Har text/element ka 'Center Point' nikalo
                    cx = (rect.left + rect.right) / 2
                    cy = (rect.top + rect.bottom) / 2
                    
                    # 🎯 SNIPER LOGIC: Agar text us invisible box ke ANDAR hai, tabhi uthao!
                    if left <= cx <= right and top <= cy <= bottom:
                        text = ""
                        
                        # 🚀 FIX: Pehle check karo ki kya ye Input Box (Edit Control) hai?
                        try:
                            # Agar Edit control hai, toh user ka type kiya hua 'Value' nikalo
                            if item.ControlType == auto.ControlType.EditControl:
                                text = item.GetValuePattern().Value
                        except: 
                            pass
                            
                        # Agar Input Box nahi hai (ya value khali hai), toh normal label (Name) uthao
                        if not text:
                            text = item.Name

                        # Text mil gaya toh save karo
                        if text and text.strip() and len(text.strip()) > 1 and text.strip() not in full_text:
                            full_text += text.strip() + "\n"
                except:
                    pass
            
            if full_text and len(full_text.strip()) > 3:
                clean_text = full_text.strip()[:3500] 
                
                # Copy to Clipboard!
                pyperclip.copy(clean_text)
                self.last_text = clean_text 
                

                
                self.label.config(text="c-ok") 
                self.root.after(1000, lambda: self.label.config(text=".")) 
            else:
                self.label.config(text="no-txt")
                self.root.after(1000, lambda: self.label.config(text=".")) 

        except Exception as e:
            self.label.config(text="ex-err")
        finally:
            self.is_processing = False
            pythoncom.CoUninitialize()

    # =======================================================
    #  F9:
    # =======================================================
    def extract_text_by_area_deep(self):
        if self.is_hidden or self.is_processing:
            return

        if self.snip_step_deep == 0:
            # Pehla F9 dabane par Top-Left corner lock hoga
            self.snip_x1, self.snip_y1 = pyautogui.position()
            self.snip_step_deep = 1
            self.label.config(text="..") # "1-dp" matlab Deep Scan ka pehla click
        else:
            # Dusra F9 dabane par Bottom-Right corner lock hoga aur Scan chalu!
            x2, y2 = pyautogui.position()
            self.snip_step_deep = 0
            self.label.config(text="..") # Deep scan processing
            
            left = min(self.snip_x1, x2)
            right = max(self.snip_x1, x2)
            top = min(self.snip_y1, y2)
            bottom = max(self.snip_y1, y2)
            
            # Naya Thread Naye Deep function ke liye
            threading.Thread(target=self.process_deep_area_extraction, args=(left, right, top, bottom), daemon=True).start()

    def process_deep_area_extraction(self, left, right, top, bottom):
        try:
            pythoncom.CoInitialize() # Thread ke andar Windows API initialize
            self.is_processing = True
            full_text = ""
            
            # 🚀 FIX: GetRootControl() hata diya. 
            # Ab jis app par click kiya (TestPad), sirf usi ka TopLevelControl scan hoga.
            # Isse Desktop, Recycle Bin aur VS Code ka kachra bilkul nahi aayega!
            main_window = auto.ControlFromPoint(int(left), int(top)).GetTopLevelControl()
            
            # 🧠 maxDepth=12 rakha hai taaki andar chhupe Radio buttons mil jayein
            for item, depth in auto.WalkControl(main_window, maxDepth=12):
                try:
                    # 🚨 SAFETY NET
                    rect = item.BoundingRectangle
                    if not rect:
                        continue
                        
                    cx = (rect.left + rect.right) / 2
                    cy = (rect.top + rect.bottom) / 2
                    
                    if left <= cx <= right and top <= cy <= bottom:
                        text = ""
                        try:
                            ctrl_type = item.ControlType
                            if ctrl_type in [auto.ControlType.EditControl, auto.ControlType.TextControl]:
                                try:
                                    text = item.GetValuePattern().Value
                                except: pass
                        except Exception:
                            pass
                            
                        if not text:
                            try:
                                text = item.Name
                            except: pass
                            
                        # Agar text valid hai aur pehle se nahi aya hai, toh save karo
                        if text and text.strip() and len(text.strip()) > 1 and text.strip() not in full_text:
                            full_text += text.strip() + "\n"
                            
                except Exception as inner_e:
                    pass 
            
            if full_text and len(full_text.strip()) > 3:
                clean_text = full_text.strip()[:3500] 
                
                # 🧠 SMART MERGE LOGIC
                if self.is_merge_mode:
                    if not self.merge_buffer:
                        # Pehli baar dabaya -> Question save karo (API ko mat bhejo)
                        self.merge_buffer = clean_text + "\n"
                        self.root.after(0, lambda: self.label.config(text="1/2"))
                        self.root.after(1000, lambda: self.label.config(text="."))
                    else:
                        # Dusri baar dabaya -> Code jod do aur API ko bhej do!
                        final_text = self.merge_buffer + clean_text
                        pyperclip.copy(final_text)
                        self.last_text = final_text
                        
                        # Kaam hone ke baad Merge Mode auto-off kar do taaki agla question normal chale
                        self.is_merge_mode = False 
                        self.merge_buffer = ""
                        
                        self.root.after(0, lambda: self.label.config(text="2/2"))
                        self.root.after(1000, lambda: self.label.config(text="."))
                else:
                    # NORMAL MODE (Agar Alt+C nahi dabaya hai toh jaise pehle chalta tha waise chalega)
                    pyperclip.copy(clean_text)
                    self.last_text = clean_text 
                    self.root.after(0, lambda: self.label.config(text="cp")) 
                    self.root.after(1000, lambda: self.label.config(text="."))  
            else:
                self.root.after(0, lambda: self.label.config(text="n-txt"))
                self.root.after(1000, lambda: self.label.config(text=".")) 

        except Exception as e:
            self.root.after(0, lambda: self.label.config(text="ex-err"))
            self.root.after(1000, lambda: self.label.config(text=".")) 
        finally:
            self.is_processing = False
            pythoncom.CoUninitialize() 
    # =======================================================


    # =======================================================
    # 🚀 F10: ULTIMATE I
    # =======================================================
    def extract_text_by_area_ia2(self):
        if self.is_hidden or self.is_processing:
            return

        if self.snip_step_ia2 == 0:
            # Pehla F10 dabane par Top-Left corner lock hoga
            self.snip_x1, self.snip_y1 = pyautogui.position()
            self.snip_step_ia2 = 1
            self.label.config(text="..") # IA2 mode pehla click
        else:
            # Dusra F10 dabane par Bottom-Right corner lock aur Scan chalu!
            x2, y2 = pyautogui.position()
            self.snip_step_ia2 = 0
            self.label.config(text="..") 
            
            left = min(self.snip_x1, x2)
            right = max(self.snip_x1, x2)
            top = min(self.snip_y1, y2)
            bottom = max(self.snip_y1, y2)
            
            # IA2 ke naye function ko background thread mein bhejo
            threading.Thread(target=self.process_ia2_area_extraction, args=(left, right, top, bottom), daemon=True).start()



    def process_ia2_area_extraction(self, left, right, top, bottom):
        try:
            pythoncom.CoInitialize()
            self.is_processing = True
            full_text = ""
            
            
            main_window = auto.ControlFromPoint(int(left), int(top)).GetTopLevelControl()
            
            # Faltu kachra block karne ke liye (TestPad Header/Footer)
            blacklist_words = ["file://", ".html"]
            
            # F9 ki tarah app ke andar ghuso (maxDepth=14 rakha hai deep scanning ke liye)
            for item, depth in auto.WalkControl(main_window, maxDepth=14):
                try:
                    rect = item.BoundingRectangle
                    if not rect:
                        continue
                        
                    cx = (rect.left + rect.right) / 2
                    cy = (rect.top + rect.bottom) / 2
                    
                    # 🎯 STRICT BOX LOGIC: Agar element F10 wale box ke strict andar hai
                    if left <= cx <= right and top <= cy <= bottom:
                        text = ""
                        
                       
                        try:
                            legacy = item.GetLegacyIAccessiblePattern()
                            if legacy:
                                text = legacy.Value
                                if not text:
                                    text = legacy.Name
                        except:
                            pass
                            
                      
                        if not text:
                            try:
                                if item.ControlType in [auto.ControlType.EditControl, auto.ControlType.TextControl, auto.ControlType.DocumentControl]:
                                    text = item.GetValuePattern().Value
                            except: pass
                            
                        if not text:
                            try: text = item.Name
                            except: pass
                            
                       
                        if text and text.strip() and len(text.strip()) > 1:
                            clean_text_line = text.strip()
                            
                            # Blacklist check
                            if any(bad_word.lower() in clean_text_line.lower() for bad_word in blacklist_words):
                                continue 
                                
                            if clean_text_line not in full_text:
                                full_text += clean_text_line + "\n"
                            
                except Exception as inner_e:
                    pass # Kisi locked element par crash na ho
            
            if full_text and len(full_text.strip()) > 3:
                clean_text = full_text.strip()[:3500] 
                
                #  SMART MERGE LOGIC
                if self.is_merge_mode:
                    if not self.merge_buffer:
                        # Pehli baar dabaya -> Question save karo (API ko mat bhejo)
                        self.merge_buffer = clean_text + "\n"
                        self.root.after(0, lambda: self.label.config(text="1/2"))
                        self.root.after(1000, lambda: self.label.config(text="."))
                    else:
                        # Dusri baar dabaya -> Code jod do aur API ko bhej do!
                        final_text = self.merge_buffer + clean_text
                        pyperclip.copy(final_text)
                        self.last_text = final_text
                        
                        # Kaam hone ke baad Merge Mode auto-off kar do taaki agla question normal chale
                        self.is_merge_mode = False 
                        self.merge_buffer = ""
                        
                        self.root.after(0, lambda: self.label.config(text="2/2"))
                        self.root.after(1000, lambda: self.label.config(text="."))
                else:
                    # NORMAL MODE (Agar Alt+C nahi dabaya hai toh jaise pehle chalta tha waise chalega)
                    pyperclip.copy(clean_text)
                    self.last_text = clean_text 
                    self.root.after(0, lambda: self.label.config(text="cp")) 
                    self.root.after(1000, lambda: self.label.config(text="."))  
            else:
                self.root.after(0, lambda: self.label.config(text="n-txt"))
                self.root.after(1000, lambda: self.label.config(text=".")) 

        except Exception as e:
            self.root.after(0, lambda: self.label.config(text="ex-err"))
            self.root.after(1000, lambda: self.label.config(text=".")) 
        finally:
            self.is_processing = False
            pythoncom.CoUninitialize()
    

    def screen_read_trigger(self):
        """Screenshot scan logic with Anti-Spam Lock"""
        if self.is_processing:
            return 
        try:
            self.is_processing = True 
            self.label.config(text="Sc")

            screenshot = None

            # --- Try MSS (Priority) ---
            try:
                with mss.MSS() as sct:
                    monitor = sct.monitors[1]
                    sct_img = sct.grab(monitor)
                    screenshot = Image.frombytes("RGB", sct_img.size, sct_img.bgra, "raw", "BGRX")
            except: pass

            # --- Try ImageGrab (Backup) ---
            if screenshot is None:
                screenshot = ImageGrab.grab()

            if screenshot:
                buffered = BytesIO()
                screenshot.save(buffered, format="JPEG", quality=50) # Fast upload
                img_str = base64.b64encode(buffered.getvalue()).decode('utf-8')
                threading.Thread(target=self.get_ai_vision_answer, args=(img_str,), daemon=True).start()

            else:
                self.label.config(text="er-img")
                self.is_processing = False

        except Exception as e:
            self.label.config(text="sc-er")
            self.is_processing = False # Error aaye toh lock khol do

    def get_ai_vision_answer(self, img_data):
        try:
            response = session.post(VERCEL_API_URL, json={'image': img_data, 'mode': self.current_mode}, timeout=60)
            if response.status_code == 200:
                answer = response.json().get('answer', '')
                if answer:
                    # Filter for useless dialogues
                    if "Please provide" in answer or "I cannot" in answer or "does not contain" in answer or "BLANK_DATA" in answer:
                        answer = "sc-er"

                    # PURANA STYLE: Hamesha copy hoga!
                    pyperclip.copy(answer) 
                    self.last_text = answer 


                    
                    if len(answer) > 15:
                        self.root.after(0, lambda: self.label.config(text="P")) 
                        self.root.after(1000, lambda: self.label.config(text="."))
                    else:
                        self.root.after(0, lambda: self.label.config(text=answer)) 

                else:
                    self.root.after(0, lambda: self.label.config(text="EMPTY"))
            else:
                self.root.after(0, lambda: self.label.config(text="sr-er"))
        except:
            self.root.after(0, lambda: self.label.config(text="TIMEOUT"))
        finally:
            self.is_processing = False # Result aane ke baad Lock khol do

    def trigger_api(self):
        if self.is_hidden: return  #  NAYA: Pause Check
        self.root.after(500, self.process_request)

    def monitor_loop(self):
        self.process_request()
        self.root.after(300, self.monitor_loop)

    def process_request(self):
        if self.is_processing:
            return

        try:
            current_text = pyperclip.paste()
            if current_text != self.last_text and len(current_text.strip()) > 5:
                # Agar clipboard mein AI ka purana answer hai, toh skip karo
                if "DONE" in current_text or "chars)" in current_text: 
                    return
                
                self.last_text = current_text
                if not self.is_hidden:
                    self.label.config(text="..")
                    self.is_processing = True
                    threading.Thread(target=self.get_ai_answer, args=(current_text,), daemon=True).start()
        except: pass

    def get_ai_answer(self, text):
        try:
            response = session.post(VERCEL_API_URL, json={'text': text, 'mode': self.current_mode}, timeout=60)
            if response.status_code == 200:
                answer = response.json().get('answer', '')
                if answer:
                    # TRICK: Agar lamba dialogue de, toh use chhota kar do
                    if "Please provide the text" in answer or answer == "BLANK_DATA":
                        answer = "C-ERR"

                    # PURANA STYLE: Bina kisi nakhre ke seedha copy!
                    pyperclip.copy(answer)
                    self.last_text = answer


                   # NAYA LOGIC: Agar answer 15 characters se bada hai (AWS ya Code), toh sirf 'P' dikhao
                    if len(answer) > 15:
                        self.root.after(0, lambda: self.label.config(text="DONE"))
                        self.root.after(1000, lambda: self.label.config(text=".")) 
                    else:
                        self.root.after(0, lambda: self.label.config(text=answer)) 


            else:
                self.root.after(0, lambda: self.label.config(text=f"sr-er"))

        except:
            self.root.after(0, lambda: self.label.config(text="TIMEOUT"))

        finally:
            # 🚀 FIX 3: API chahe PASS ho, FAIL ho, ya CRASH ho.. Lock hamesha khulna chahiye!
            self.is_processing = False
 

    def stealth_hide(self):
        self.is_hidden = True
        self.is_paused = True   #  NAYA: aaya ->  PAUSE
        self.root.withdraw()
        self.code_window.withdraw()  #  NAYA:  aaye toh Code Box bhi chhupa do!
        self.is_code_visible = False
        #   ke aate hi mash mode bhi band karo
        if getattr(self, 'mash_hook', None):
            keyboard.unhook(self.mash_hook)
            self.mash_hook = None

    def stealth_show(self):
        self.is_hidden = False
        self.root.deiconify()

    def panic_exit(self):
        os._exit(0)

    def auto_hide(self):
        self.label.config(text=".")

    def toggle_merge_mode(self):
        """Alt + C dabane par Merge Mode ON/OFF karega"""
        if self.is_hidden: return
        
        self.is_merge_mode = not self.is_merge_mode
        self.merge_buffer = "" # Mode change hote hi purana kachra saaf
        
        if self.is_merge_mode:
            self.label.config(text="m-on")  # Merge ON
        else:
            self.label.config(text="m-off") # Merge OFF
            
        self.root.after(1000, lambda: self.label.config(text="."))

   # 🚀 NAYA FUNCTION: Smart Play/Pause & Ghost Character Fix
    def force_paste(self):
        if self.is_hidden: 
            return 
        
        try:
            raw_clipboard = pyperclip.paste()
            # GHOST CHARACTER FIX: Nakli spaces saaf karo
            current_clipboard = raw_clipboard.replace('\xa0', ' ').replace('\r\n', '\n').replace('*', '')
            
            if self.is_typing and self.text_to_type != current_clipboard:
                self.is_typing = False 
                time.sleep(0.1)        
                
            if self.is_typing:
                if self.is_paused:
                    self.is_paused = False  
                    self.label.config(text="t..")
                    self.root.after(1000, lambda: self.label.config(text=".."))
                else:
                    self.is_paused = True   
                    self.label.config(text="psd")
                    self.root.after(1000, lambda: self.label.config(text="."))
            else:
                self.text_to_type = current_clipboard
                if self.text_to_type:
                    self.label.config(text="t..")
                    self.root.after(1000, lambda: self.label.config(text=".."))
                    self.type_index = 0
                    self.is_typing = True
                    self.is_paused = False
                    threading.Thread(target=self.type_worker, daemon=True).start()
        except:
            pass

    def type_worker(self):
        try:
            time.sleep(0.5) # Ungli hatane ka time
            
            # 🚀 STUCK KEY FIX: Zabardasti Alt button ko release karo!
            keyboard.release('alt')
            pyautogui.keyUp('alt')
            
            is_start_of_line = True  
            was_paused = False  
            
            while self.type_index < len(self.text_to_type) and self.is_typing:
                if self.is_paused:
                    was_paused = True 
                    time.sleep(0.1) 
                    continue
                    
                if was_paused:
                    time.sleep(0.5) 
                    was_paused = False
                    # Resume hone par wapas check karo ki Alt daba toh nahi
                    keyboard.release('alt')
                    pyautogui.keyUp('alt')

                char = self.text_to_type[self.type_index]
                
                # 🚀 ENTER KEY FIX: Nayi line ke liye explicit 'enter' press
                if char == '\n':
                    is_start_of_line = True
                    pyautogui.press('enter') 
                    self.type_index += 1
                    continue
                    
                # STAIRCASE FIX: Faltu spaces skip karo
                if is_start_of_line and char in [' ', '\t']:
                    self.type_index += 1
                    continue 
                    
                is_start_of_line = False
                
                # Main character typing
                pyautogui.write(char)
                self.type_index += 1
                
                # speed (Anti)
                time.sleep(random.uniform(0.04, 0.06)) 
                
            # Loop complete ho gaya
            if self.is_typing: 
                self.is_typing = False
                if not self.is_hidden:
                    self.label.config(text="d")
                    self.root.after(1000, lambda: self.label.config(text="."))
                    
        except Exception as e:
            #  SAFETY NET: Agar koi character crash kare, toh 'ERR' dikhaye
            self.is_typing = False
            if not self.is_hidden:
                self.label.config(text="err")

    
    #  NAYA FUNCTION 1: Mash-to-Type Setup (SMART RESUME + STAIRCASE FIX)
    def start_mash_mode(self):
        if self.is_hidden: return
        try:
            # Clipboard se code uthao, faltu spaces clean karo
            current_clipboard = pyperclip.paste().replace('\xa0', ' ').replace('\r\n', '\n').replace('**', '')
            
            # Agar pehle se mode ON hai, toh usko OFF kar do (PAUSE)
            if getattr(self, 'mash_hook', None):
                keyboard.unhook(self.mash_hook)
                self.mash_hook = None
                self.label.config(text="m-off")
                self.root.after(1000, lambda: self.label.config(text=".")) 
                return

            # Naya question aane par reset karo
            if getattr(self, 'mash_text', '') != current_clipboard:
                self.mash_text = current_clipboard
                self.mash_index = 0
                self.is_start_of_line = True #  NAYA: First line track karne ke liye set kiya

            if self.mash_text:
                self.label.config(text="m-on")
                self.root.after(1000, lambda: self.label.config(text=".")) 
                
                # Ye Keyboard interceptor hai! Ye tumhari dabayi har key ko hide kar lega
                self.mash_hook = keyboard.on_press(self.mash_callback, suppress=True)
        except Exception as e: 
            pass

    # 🚀 NAYA FUNCTION 2: Har random button (SUPER FAST SKIP)
    def mash_callback(self, event):
        # Sirf key dabane (KEY_DOWN) par chalega
        if event.event_type != keyboard.KEY_DOWN:
            return True 
            
        # 🚨 SAFETY: Enter, Backspace, Space normal kaam karenge
        if len(event.name) > 1 or event.name == 'space':
            return True 

        if self.mash_index < len(self.mash_text):
            
            # 🚀 SUPER FAST SKIP: Nayi line aate hi saare faltu spaces ek second me skip karo!
            while getattr(self, 'is_start_of_line', False) and self.mash_index < len(self.mash_text) and self.mash_text[self.mash_index] in [' ', '\t']:
                self.mash_index += 1
                
            # Agar spaces skip karte-karte code khatam ho jaye
            if self.mash_index >= len(self.mash_text):
                keyboard.unhook(self.mash_hook)
                self.mash_hook = None
                self.label.config(text="d-dn")
                self.root.after(1000, lambda: self.label.config(text="."))
                return False

            char = self.mash_text[self.mash_index]
                
            # Nayi line (Enter) handle karo
            if char == '\n':
                keyboard.send('enter')
                self.is_start_of_line = True  # Agli line ko fir se nayi line maan lo
            else:
                keyboard.write(char)
                self.is_start_of_line = False # Character aate hi skip mode off kar do
                
            self.mash_index += 1
            
            # Code pura hone par interceptor hata do
            if self.mash_index >= len(self.mash_text):
                keyboard.unhook(self.mash_hook)
                self.mash_hook = None
                self.label.config(text="m-dn")
                self.root.after(1000, lambda: self.label.config(text="."))

            return False 
            
        return True

                
    def update_ui(self):
        try:
            x, y = self.root.winfo_pointerxy()
            
            if not self.is_hidden:               
                self.root.geometry(f"+{x+22}+{y+22}")

                # PANIC MOUSE SHAKE SENSOR
            if self.is_code_visible:
                # Agar mouse open position se 50 pixel door gaya, toh turant hide kar do!
                if abs(x - getattr(self, 'open_x', x)) > 50 or abs(y - getattr(self, 'open_y', y)) > 50:
                    self.code_window.withdraw()
                    self.is_code_visible = False

            self.root.after(30, self.update_ui)
        except: pass

        #  NAYA FUNCTION: Code Preview Toggle
    def toggle_code_view(self):
        if self.is_hidden: 
            return # Agar app hidden mode mein hai toh mat kholo
            
        if self.is_code_visible:
           
            self.code_window.withdraw()
            self.is_code_visible = False
        else:
            
            current_data = pyperclip.paste()
            self.code_text.delete('1.0', tk.END) # Purana clear karo
            self.code_text.insert(tk.END, current_data) # Naya daalo
            
            
            x, y = self.root.winfo_pointerxy()

            # 🚨 SENSOR: Open hote time mouse kahan hai, wo yaad rakho
            self.open_x = x
            self.open_y = y

            self.code_window.geometry(f"+{x+30}+{y+30}")
            self.code_window.deiconify() # Box dikhao
            self.is_code_visible = True

    #  NAYA FUNCTION: Invisible Stealth Scrolling
    def scroll_up(self):
        
        if self.is_code_visible:
            try:
                
                self.code_text.yview_scroll(-2, "units")
            except: pass

    def scroll_down(self):
        if self.is_code_visible:
            try:
                
                self.code_text.yview_scroll(2, "units")
            except: pass



if __name__ == "__main__":
    app = IQPointer()