import argparse
import ctypes
import json
import time
from ctypes import wintypes
from pathlib import Path
from PIL import ImageGrab

user32 = ctypes.windll.user32

class RECT(ctypes.Structure):
    _fields_ = [('left', ctypes.c_long), ('top', ctypes.c_long), ('right', ctypes.c_long), ('bottom', ctypes.c_long)]
class POINT(ctypes.Structure):
    _fields_ = [('x', ctypes.c_long), ('y', ctypes.c_long)]
EnumWindowsProc = ctypes.WINFUNCTYPE(ctypes.c_bool, wintypes.HWND, wintypes.LPARAM)

def enum_windows():
    out = []
    def cb(hwnd, lparam):
        if user32.IsWindowVisible(hwnd):
            n = user32.GetWindowTextLengthW(hwnd)
            if n > 0:
                buf = ctypes.create_unicode_buffer(n + 1)
                user32.GetWindowTextW(hwnd, buf, n + 1)
                r = RECT(); user32.GetWindowRect(hwnd, ctypes.byref(r))
                pid = wintypes.DWORD(); user32.GetWindowThreadProcessId(hwnd, ctypes.byref(pid))
                out.append({'hwnd': int(hwnd), 'title': buf.value, 'pid': int(pid.value), 'rect': [r.left, r.top, r.right, r.bottom], 'size': [r.right-r.left, r.bottom-r.top]})
        return True
    user32.EnumWindows(EnumWindowsProc(cb), 0)
    return out

def find_title(substr):
    for w in enum_windows():
        if substr.lower() in w['title'].lower(): return w
    return None

def hide_blockers():
    hidden=[]
    for w in enum_windows():
        t=w['title'].lower()
        if w['title']=='Michel' or 'cmd.exe' in t or 'powershell' in t:
            user32.ShowWindowAsync(wintypes.HWND(w['hwnd']), 6)
            hidden.append(w)
    return hidden

def focus_mcsj():
    w=find_title('MCSJ - 2026.1')
    if not w: return None
    hwnd=wintypes.HWND(w['hwnd'])
    user32.ShowWindowAsync(hwnd, 9)
    user32.SetForegroundWindow(hwnd)
    return w

def capture(path):
    Path(path).parent.mkdir(parents=True, exist_ok=True)
    img=ImageGrab.grab(); img.save(path)
    return {'path': str(path), 'size': list(img.size)}

def cursor():
    pt=POINT(); user32.GetCursorPos(ctypes.byref(pt)); return [pt.x, pt.y]

def checked_click(x,y):
    before=cursor()
    ok=bool(user32.SetCursorPos(int(x), int(y)))
    mid=cursor()
    if ok:
        user32.mouse_event(0x0002,0,0,0,0); time.sleep(.05); user32.mouse_event(0x0004,0,0,0,0)
    return {'requested':[int(x),int(y)], 'set_cursor_ok':ok, 'before':before, 'mid':mid, 'after':cursor(), 'clicked':ok}

def main():
    ap=argparse.ArgumentParser(); ap.add_argument('cmd', choices=['windows','prep','capture','click']); ap.add_argument('args', nargs='*'); ns=ap.parse_args()
    if ns.cmd=='windows': print(json.dumps({'windows': enum_windows(), 'cursor': cursor()}, indent=2))
    elif ns.cmd=='prep':
        hidden=hide_blockers(); w=focus_mcsj(); time.sleep(.5); print(json.dumps({'hidden': hidden, 'mcsj': w, 'cursor': cursor()}, indent=2))
    elif ns.cmd=='capture': print(json.dumps(capture(ns.args[0] if ns.args else r'C:\MCSJAgent\proof\mcsj-capture.png'), indent=2))
    elif ns.cmd=='click':
        if len(ns.args)<2: raise SystemExit('usage: click X Y')
        print(json.dumps(checked_click(ns.args[0], ns.args[1]), indent=2))
if __name__=='__main__': main()
