// OS input injection for Windows via user32 SendInput (koffi FFI).
// On non-Windows platforms, exports a stub that logs instead of injecting,
// so the agent can run in dev/test environments.

const { toVirtualKey } = require('./keymap');

const MOUSEEVENTF_MOVE = 0x0001;
const MOUSEEVENTF_ABSOLUTE = 0x8000;
const MOUSEEVENTF_LEFTDOWN = 0x0002;
const MOUSEEVENTF_LEFTUP = 0x0004;
const MOUSEEVENTF_RIGHTDOWN = 0x0008;
const MOUSEEVENTF_RIGHTUP = 0x0010;
const MOUSEEVENTF_MIDDLEDOWN = 0x0020;
const MOUSEEVENTF_MIDDLEUP = 0x0040;
const MOUSEEVENTF_WHEEL = 0x0800;
const KEYEVENTF_KEYUP = 0x0002;
const INPUT_MOUSE = 0;
const INPUT_KEYBOARD = 1;

const BUTTON_DOWN = { 0: MOUSEEVENTF_LEFTDOWN, 1: MOUSEEVENTF_MIDDLEDOWN, 2: MOUSEEVENTF_RIGHTDOWN };
const BUTTON_UP = { 0: MOUSEEVENTF_LEFTUP, 1: MOUSEEVENTF_MIDDLEUP, 2: MOUSEEVENTF_RIGHTUP };

function createWindowsInjector() {
  const koffi = require('koffi');
  const user32 = koffi.load('user32.dll');

  const MOUSEINPUT = koffi.struct('MOUSEINPUT', {
    dx: 'long', dy: 'long', mouseData: 'int32',
    dwFlags: 'uint32', time: 'uint32', dwExtraInfo: 'uintptr_t',
  });
  const KEYBDINPUT = koffi.struct('KEYBDINPUT', {
    wVk: 'uint16', wScan: 'uint16',
    dwFlags: 'uint32', time: 'uint32', dwExtraInfo: 'uintptr_t',
  });
  const HARDWAREINPUT = koffi.struct('HARDWAREINPUT', {
    uMsg: 'uint32', wParamL: 'uint16', wParamH: 'uint16',
  });
  const INPUT_UNION = koffi.union('INPUT_UNION', {
    mi: MOUSEINPUT, ki: KEYBDINPUT, hi: HARDWAREINPUT,
  });
  const INPUT = koffi.struct('INPUT', { type: 'uint32', u: INPUT_UNION });

  const SendInput = user32.func('uint32 SendInput(uint32 cInputs, INPUT *pInputs, int cbSize)');
  const INPUT_SIZE = koffi.sizeof(INPUT);

  function sendMouse(mi) {
    SendInput(1, [{ type: INPUT_MOUSE, u: { mi: