import type { Page } from '@playwright/test'

export interface TouchPoint {
  /** Stable id for ONE finger's contact across start/move/end calls — CDP
   * needs this to tell "the same finger moved" apart from "a finger lifted
   * and a different one landed", especially once more than one point is
   * ever in flight (spec c: multi-touch). */
  id: number
  x: number
  y: number
}

export interface RealTouch {
  start(points: TouchPoint[]): Promise<void>
  move(points: TouchPoint[]): Promise<void>
  /** `points`: the point(s) BEING RELEASED by this call, at their last known
   * coordinates — NOT the ones continuing (empirically verified against
   * Chromium/CDP: passing the still-down point here ends THAT one instead;
   * this is the opposite of `start`/`move`, where `points` is every
   * currently-active point). Releasing a 2nd-of-2 touch: pass ONLY that
   * one. Releasing the last remaining touch: pass that one too — an empty
   * array is deliberately not treated as a shorthand for "end everything
   * still active" anywhere in this suite, to avoid relying on the same
   * ambiguity that made this comment necessary in the first place. */
  end(points: TouchPoint[]): Promise<void>
}

/** Real, browser-native multi-touch dispatch via CDP's `Input.
 * dispatchTouchEvent` — Playwright's own high-level `page.touchscreen` API
 * only exposes a single-point `tap()` (touchstart+touchend, no move, no
 * second concurrent contact), which cannot drive vsm-editor.tsx's
 * `isPrimary`/`activePointerIdRef` multi-pointer guard OR a touch DRAG at
 * all (P8.2b jsdom-Lückenliste: "Echtes Multi-Touch/Pinch in jsdom nicht
 * simulierbar — isPrimary/activePointerIdRef-Logik nur durch synthetische
 * Einzel-Pointer-Events mit isPrimary:false getestet"). CDP's Input domain
 * dispatches REAL touch events that Chromium itself promotes to REAL
 * PointerEvents (first concurrent touch → isPrimary:true; any ADDITIONAL
 * concurrent touch → isPrimary:false, a distinct pointerId) — not a
 * JS-constructed PointerEvent, the same class of genuine browser semantics
 * as `page.mouse`. Requires the browser context to have `hasTouch: true`
 * (`test.use({ hasTouch: true })`) — otherwise Chromium does not treat the
 * page as touch-capable and these events would not promote to pointer
 * events with `pointerType: 'touch'` at all. */
export async function createRealTouch(page: Page): Promise<RealTouch> {
  const client = await page.context().newCDPSession(page)
  return {
    async start(points: TouchPoint[]) {
      await client.send('Input.dispatchTouchEvent', { type: 'touchStart', touchPoints: points })
    },
    async move(points: TouchPoint[]) {
      await client.send('Input.dispatchTouchEvent', { type: 'touchMove', touchPoints: points })
    },
    async end(points: TouchPoint[]) {
      await client.send('Input.dispatchTouchEvent', { type: 'touchEnd', touchPoints: points })
    },
  }
}
