"""Capture desktop screenshots for tour debugging. Zero pip deps — Win32 only."""
import ctypes
import ctypes.wintypes
import struct
import sys
import zlib

user32 = ctypes.windll.user32
gdi32 = ctypes.windll.gdi32

# Make this process DPI-aware so we capture at the real physical resolution.
# Without this, topmost/overlay windows may not appear in the capture on
# high-DPI (125%/150%) displays.
try:
    user32.SetProcessDPIAware()
except Exception:
    pass


def capture_screen(path: str):
    """Capture the entire screen to a PNG file."""
    w = user32.GetSystemMetrics(0)  # SM_CXSCREEN (physical after DPI-aware)
    h = user32.GetSystemMetrics(1)  # SM_CYSCREEN

    hdc_screen = user32.GetDC(0)
    hdc_mem = gdi32.CreateCompatibleDC(hdc_screen)
    hbmp = gdi32.CreateCompatibleBitmap(hdc_screen, w, h)
    gdi32.SelectObject(hdc_mem, hbmp)
    gdi32.BitBlt(hdc_mem, 0, 0, w, h, hdc_screen, 0, 0, 0x00CC0020)  # SRCCOPY

    # Read bitmap bits
    class BITMAPINFOHEADER(ctypes.Structure):
        _fields_ = [
            ("biSize", ctypes.c_uint32), ("biWidth", ctypes.c_int32),
            ("biHeight", ctypes.c_int32), ("biPlanes", ctypes.c_uint16),
            ("biBitCount", ctypes.c_uint16), ("biCompression", ctypes.c_uint32),
            ("biSizeImage", ctypes.c_uint32), ("biXPelsPerMeter", ctypes.c_int32),
            ("biYPelsPerMeter", ctypes.c_int32), ("biClrUsed", ctypes.c_uint32),
            ("biClrImportant", ctypes.c_uint32),
        ]

    bmi = BITMAPINFOHEADER()
    bmi.biSize = ctypes.sizeof(BITMAPINFOHEADER)
    bmi.biWidth = w
    bmi.biHeight = -h  # top-down
    bmi.biPlanes = 1
    bmi.biBitCount = 32
    bmi.biCompression = 0  # BI_RGB

    buf_size = w * h * 4
    buf = ctypes.create_string_buffer(buf_size)
    gdi32.GetDIBits(hdc_mem, hbmp, 0, h, buf, ctypes.byref(bmi), 0)

    # Clean up GDI
    gdi32.DeleteObject(hbmp)
    gdi32.DeleteDC(hdc_mem)
    user32.ReleaseDC(0, hdc_screen)

    # Convert BGRA -> RGB and write PNG manually
    raw = buf.raw
    _write_png(path, w, h, raw)
    print(f"Screenshot saved: {path} ({w}x{h})")

def _write_png(path, w, h, bgra_data):
    """Write a minimal PNG from BGRA pixel data."""
    # Convert BGRA rows to RGB with filter byte
    rows = []
    for y in range(h):
        row = bytearray([0])  # filter: None
        offset = y * w * 4
        for x in range(w):
            px = offset + x * 4
            b, g, r = bgra_data[px], bgra_data[px+1], bgra_data[px+2]
            row.extend([r, g, b])
        rows.append(bytes(row))
    raw_data = b"".join(rows)
    compressed = zlib.compress(raw_data, 6)

    def _chunk(ctype, data):
        c = ctype + data
        return struct.pack(">I", len(data)) + c + struct.pack(">I", zlib.crc32(c) & 0xFFFFFFFF)

    with open(path, "wb") as f:
        f.write(b"\x89PNG\r\n\x1a\n")
        f.write(_chunk(b"IHDR", struct.pack(">IIBBBBB", w, h, 8, 2, 0, 0, 0)))
        f.write(_chunk(b"IDAT", compressed))
        f.write(_chunk(b"IEND", b""))

if __name__ == "__main__":
    out = sys.argv[1] if len(sys.argv) > 1 else "screenshot.png"
    capture_screen(out)
