/**
 * Canvas interaction utilities for UI testing
 */

/**
 * Reset canvas scroll/pan to origin
 */
export async function resetCanvasView() {
  await browser.execute(function() {
    if (window.context && window.context.stageWidget) {
      window.context.stageWidget.offsetX = 0;
      window.context.stageWidget.offsetY = 0;
      // Trigger redraw to apply the reset
      if (window.context.updateUI) {
        window.context.updateUI();
      }
    }
  });
  await browser.pause(100); // Wait for canvas to reset
}

/**
 * Click at specific coordinates on the canvas
 * @param {number} x - X coordinate relative to canvas
 * @param {number} y - Y coordinate relative to canvas
 */
export async function clickCanvas(x, y) {
  await resetCanvasView();
  await browser.clickCanvas(x, y);
  await browser.pause(100); // Wait for render
}

/**
 * Drag from one point to another on the canvas
 * @param {number} fromX - Starting X coordinate
 * @param {number} fromY - Starting Y coordinate
 * @param {number} toX - Ending X coordinate
 * @param {number} toY - Ending Y coordinate
 */
export async function dragCanvas(fromX, fromY, toX, toY) {
  await resetCanvasView();
  await browser.dragCanvas(fromX, fromY, toX, toY);
  await browser.pause(200); // Wait for render
}

/**
 * Draw a rectangle on the canvas
 * @param {number} x - Top-left X coordinate
 * @param {number} y - Top-left Y coordinate
 * @param {number} width - Rectangle width
 * @param {number} height - Rectangle height
 * @param {boolean} filled - Whether to fill the shape (default: true)
 * @param {string} color - Fill color in hex format (e.g., '#ff0000')
 */
export async function drawRectangle(x, y, width, height, filled = true, color = null) {
  // Select the rectangle tool
  await selectTool('rectangle');

  // Set fill option and color if provided
  await browser.execute((filled, color) => {
    if (window.context) {
      window.context.fillShape = filled;
      if (color) {
        window.context.fillStyle = color;
      }
    }
  }, filled, color);

  // Draw by dragging from start to end point
  await dragCanvas(x, y, x + width, y + height);

  // Wait for shape to be created
  await browser.pause(300);
}

/**
 * Draw an ellipse on the canvas
 * @param {number} x - Top-left X coordinate
 * @param {number} y - Top-left Y coordinate
 * @param {number} width - Ellipse width
 * @param {number} height - Ellipse height
 * @param {boolean} filled - Whether to fill the shape (default: true)
 */
export async function drawEllipse(x, y, width, height, filled = true) {
  // Select the ellipse tool
  await selectTool('ellipse');

  // Set fill option
  await browser.execute((filled) => {
    if (window.context) {
      window.context.fillShape = filled;
    }
  }, filled);

  // Draw by dragging from start to end point
  await dragCanvas(x, y, x + width, y + height);

  // Wait for shape to be created
  await browser.pause(300);
}

/**
 * Select a tool from the toolbar
 * @param {string} toolName - Name of the tool ('rectangle', 'ellipse', 'brush', etc.)
 */
export async function selectTool(toolName) {
  const toolButton = await browser.$(`[data-tool="${toolName}"]`);
  await toolButton.click();
  await browser.pause(100);
}

/**
 * Select multiple shapes by dragging a selection box over them
 * @param {Array<{x: number, y: number}>} points - Array of points representing shapes to select
 */
export async function selectMultipleShapes(points) {
  // First, make sure we're in select mode
  await selectTool('select');

  // Calculate bounding box that encompasses all points
  const minX = Math.min(...points.map(p => p.x)) - 10;
  const minY = Math.min(...points.map(p => p.y)) - 10;
  const maxX = Math.max(...points.map(p => p.x)) + 10;
  const maxY = Math.max(...points.map(p => p.y)) + 10;

  // Drag a selection box from top-left to bottom-right
  await dragCanvas(minX, minY, maxX, maxY);
  await browser.pause(200);
}

/**
 * Use keyboard shortcut / menu action
 * Since Tauri menu shortcuts don't reach the browser, we invoke actions directly
 * @param {string} key - Key to press (e.g., 'g' for group)
 * @param {boolean} withCtrl - Whether to hold Ctrl (ignored, kept for compatibility)
 */
export async function useKeyboardShortcut(key, withCtrl = true) {
  if (key === 'g') {
    // Call group action directly without serializing the whole function
    await browser.execute('window.actions.group.create()');
  }

  await browser.pause(300); // Give time for the action to process
}

/**
 * Get pixel color at specific coordinates (requires canvas access)
 * @param {number} x - X coordinate
 * @param {number} y - Y coordinate
 * @returns {Promise<string>} Color in hex format
 */
export async function getPixelColor(x, y) {
  const result = await browser.execute(function(x, y) {
    const canvas = document.querySelector('canvas.stage');
    if (!canvas) return null;

    const ctx = canvas.getContext('2d');
    const imageData = ctx.getImageData(x, y, 1, 1);
    const data = imageData.data;

    // Convert to hex
    const r = data[0].toString(16).padStart(2, '0');
    const g = data[1].toString(16).padStart(2, '0');
    const b = data[2].toString(16).padStart(2, '0');

    return `#${r}${g}${b}`;
  }, x, y);

  return result;
}

/**
 * Check if a shape exists at given coordinates by checking if pixel is not background
 * @param {number} x - X coordinate
 * @param {number} y - Y coordinate
 * @param {string} backgroundColor - Expected background color (default white)
 * @returns {Promise<boolean>}
 */
export async function hasShapeAt(x, y, backgroundColor = '#ffffff') {
  const color = await getPixelColor(x, y);
  return color && color.toLowerCase() !== backgroundColor.toLowerCase();
}

/**
 * Double-click at specific coordinates on the canvas (to enter group editing mode)
 * @param {number} x - X coordinate relative to canvas
 * @param {number} y - Y coordinate relative to canvas
 */
export async function doubleClickCanvas(x, y) {
  const canvas = await browser.$('canvas.stage');
  const location = await canvas.getLocation();

  // Perform double-click using performActions
  await browser.performActions([{
    type: 'pointer',
    id: 'mouse',
    parameters: { pointerType: 'mouse' },
    actions: [
      { type: 'pointerMove', duration: 0, x: location.x + x, y: location.y + y },
      { type: 'pointerDown', button: 0 },
      { type: 'pointerUp', button: 0 },
      { type: 'pause', duration: 50 },
      { type: 'pointerDown', button: 0 },
      { type: 'pointerUp', button: 0 }
    ]
  }]);

  await browser.pause(300); // Wait for group to be entered
}

/**
 * Set the timeline playhead to a specific time
 * @param {number} time - Time in seconds
 */
export async function setPlayheadTime(time) {
  await browser.execute(function(timeValue) {
    if (window.context && window.context.activeObject) {
      // Set time on both the active object and timeline state
      window.context.activeObject.currentTime = timeValue;
      if (window.context.timelineWidget && window.context.timelineWidget.timelineState) {
        window.context.timelineWidget.timelineState.currentTime = timeValue;
      }

      // Trigger timeline redraw to show updated playhead position
      if (window.context.timelineWidget && window.context.timelineWidget.requestRedraw) {
        window.context.timelineWidget.requestRedraw();
      }

      // Trigger stage redraw to show shapes at new time
      if (window.context.updateUI) {
        window.context.updateUI();
      }
    }
  }, time);
  await browser.pause(200);
}

/**
 * Get the current playhead time
 * @returns {Promise<number>} Current time in seconds
 */
export async function getPlayheadTime() {
  return await browser.execute(function() {
    if (window.context && window.context.activeObject) {
      return window.context.activeObject.currentTime;
    }
    return 0;
  });
}

/**
 * Add a keyframe at the current playhead position for selected shapes/objects
 */
export async function addKeyframe() {
  await browser.execute('window.addKeyframeAtPlayhead && window.addKeyframeAtPlayhead()');
  await browser.pause(200);
}
