"use strict";

const assert = require("node:assert/strict");
const path = require("node:path");
const test = require("node:test");

const repositoryRoot = path.resolve(__dirname, "..", "..");
const cutDrag = require(path.join(
  repositoryRoot,
  "src",
  "MBN_STOCK_WEBVIEW.LegacyParityApp",
  "Web",
  "legacy-cut-drag.js"));

test("creates the original asymmetric mouse-down rectangle", () => {
  const rectangle = cutDrag.createDragRectangle(
    { x: 100, y: 80 },
    { width: 10, height: 6 });

  assert.deepEqual(rectangle, {
    left: 90,
    top: 74,
    width: 10,
    height: 6,
    right: 100,
    bottom: 80
  });
  assert.equal(Object.isFrozen(rectangle), true);
});

test("matches Rectangle.Contains right/bottom-exclusive drag decisions", () => {
  const down = { x: 100, y: 80 };
  const rectangle = cutDrag.createDragRectangle(
    down,
    { width: 10, height: 6 });

  assert.equal(cutDrag.shouldStart(rectangle, down), true, "same point");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 101, y: 79 }), true, "right");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 99, y: 81 }), true, "down");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 89, y: 79 }), true, "left boundary crossed");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 99, y: 73 }), true, "top boundary crossed");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 90, y: 74 }), false, "inside upper-left");

  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 90, y: 79 }), false, "left is inclusive");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 99, y: 74 }), false, "top is inclusive");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 100, y: 79 }), true, "right is exclusive");
  assert.equal(
    cutDrag.shouldStart(rectangle, { x: 99, y: 80 }), true, "bottom is exclusive");
});

test("validates finite coordinates and positive finite drag sizes", () => {
  const validSize = { width: 4, height: 4 };

  for (const down of [
    null,
    { x: Number.NaN, y: 0 },
    { x: 0, y: Number.POSITIVE_INFINITY },
    { x: "0", y: 0 }
  ]) {
    assert.throws(
      () => cutDrag.createDragRectangle(down, validSize),
      TypeError);
  }

  for (const dragSize of [
    null,
    { width: 0, height: 1 },
    { width: 1, height: -1 },
    { width: Number.NaN, height: 1 },
    { width: 1, height: Number.POSITIVE_INFINITY }
  ]) {
    assert.throws(
      () => cutDrag.createDragRectangle({ x: 0, y: 0 }, dragSize),
      RangeError);
  }

  const rectangle = cutDrag.createDragRectangle(
    { x: 4, y: 4 },
    validSize);
  assert.throws(
    () => cutDrag.shouldStart(rectangle, { x: Number.NaN, y: 0 }),
    TypeError);
});

test("maps DIP metrics to CSS pixels at 100 and 150 percent host DPI", () => {
  assert.deepEqual(cutDrag.toCssDragSize(
    { width: 4, height: 6 }, 1, 1),
  { width: 4, height: 6 });
  assert.deepEqual(cutDrag.toCssDragSize(
    { width: 4, height: 6 }, 1.5, 1.5),
  { width: 4, height: 6 });
});

test("accounts for a retained WebView browser zoom in pointer CSS coordinates", () => {
  assert.deepEqual(cutDrag.toCssDragSize(
    { width: 4, height: 6 }, 1.5, 1.875),
  { width: 3.2, height: 4.8 });
  assert.deepEqual(cutDrag.toCssDragSize(
    { width: 4, height: 6 }, 1, 1.25),
  { width: 3.2, height: 4.8 });
});

test("keeps fractional CSS boundaries after retained zoom conversion", () => {
  const size = cutDrag.toCssDragSize({ width: 4, height: 4 }, 1, 1.25);
  const rectangle = cutDrag.createDragRectangle({ x: 10.5, y: 10.5 }, size);

  assert.equal(cutDrag.shouldStart(rectangle, { x: 7.31, y: 7.31 }), false);
  assert.equal(cutDrag.shouldStart(rectangle, { x: 7.29, y: 7.31 }), true);
  assert.equal(cutDrag.shouldStart(rectangle, { x: 7.31, y: 7.29 }), true);
  assert.equal(cutDrag.shouldStart(rectangle, { x: 10.5, y: 10.49 }), true);
});

test("uses a neutral zoom ratio for missing or abnormal scale measurements", () => {
  for (const scales of [
    [0, 0],
    [Number.NaN, Number.NaN],
    [1, Number.POSITIVE_INFINITY],
    [1, 0.1],
    [1, 10]
  ]) {
    assert.deepEqual(cutDrag.toCssDragSize(
      { width: 4, height: 6 }, scales[0], scales[1]),
    { width: 4, height: 6 });
  }
});

test("publishes the same API as a browser global", () => {
  assert.equal(globalThis.LegacyCutDrag, cutDrag);
  assert.equal(typeof cutDrag.createDragRectangle, "function");
  assert.equal(typeof cutDrag.shouldStart, "function");
  assert.equal(typeof cutDrag.toCssDragSize, "function");
});
