export interface AsukaCurvedGlyphGeometry {
  x: number;
  y: number;
  angle: number;
  width: number;
  left?: number;
  right?: number;
  ascent: number;
  descent: number;
}

export interface AsukaCurvedTextSelectionBounds {
  minX: number;
  minY: number;
  maxX: number;
  maxY: number;
  centerX: number;
  centerY: number;
  width: number;
  height: number;
  padding: number;
}

/** Compute the tight visual bounds that contain every rotated path glyph. */
export function computeCurvedTextSelectionBounds(
  glyphs: readonly AsukaCurvedGlyphGeometry[],
  padding = 0,
): AsukaCurvedTextSelectionBounds | null {
  let minX = Infinity;
  let minY = Infinity;
  let maxX = -Infinity;
  let maxY = -Infinity;

  glyphs.forEach((glyph) => {
    const x = Number(glyph.x);
    const y = Number(glyph.y);
    const angle = Number(glyph.angle) || 0;
    const halfWidth = Math.max(0, Number(glyph.width) || 0) / 2;
    const left = Number.isFinite(Number(glyph.left))
      ? Math.max(0, Number(glyph.left))
      : halfWidth;
    const right = Number.isFinite(Number(glyph.right))
      ? Math.max(0, Number(glyph.right))
      : halfWidth;
    const ascent = Math.max(0, Number(glyph.ascent) || 0);
    const descent = Math.max(0, Number(glyph.descent) || 0);
    if (![x, y, left, right, ascent, descent].every(Number.isFinite)) return;

    const cos = Math.cos(angle);
    const sin = Math.sin(angle);
    const corners: Array<[number, number]> = [
      [-left, -ascent],
      [right, -ascent],
      [right, descent],
      [-left, descent],
    ];

    corners.forEach(([localX, localY]) => {
      const rotatedX = x + localX * cos - localY * sin;
      const rotatedY = y + localX * sin + localY * cos;
      minX = Math.min(minX, rotatedX);
      minY = Math.min(minY, rotatedY);
      maxX = Math.max(maxX, rotatedX);
      maxY = Math.max(maxY, rotatedY);
    });
  });

  if (![minX, minY, maxX, maxY].every(Number.isFinite)) return null;

  const safePadding = Math.max(0, Number(padding) || 0);

  return {
    minX,
    minY,
    maxX,
    maxY,
    centerX: (minX + maxX) / 2,
    centerY: (minY + maxY) / 2,
    width: Math.max(1, maxX - minX + safePadding * 2),
    height: Math.max(1, maxY - minY + safePadding * 2),
    padding: safePadding,
  };
}
