import { describe, expect, it } from 'vitest';
import {
  boundsFromCorners,
  computeHomography,
  isValidCardQuad,
  orderQuadCorners,
} from '../../lib/scanner-card-warp.js';

describe('orderQuadCorners', () => {
  it('orders corners as top-left, top-right, bottom-right, bottom-left', () => {
    const points = [
      { x: 10, y: 10 },
      { x: 90, y: 12 },
      { x: 88, y: 140 },
      { x: 12, y: 138 },
    ];

    expect(orderQuadCorners(points)).toEqual([
      { x: 10, y: 10 },
      { x: 90, y: 12 },
      { x: 88, y: 140 },
      { x: 12, y: 138 },
    ]);
  });
});

describe('boundsFromCorners', () => {
  it('returns the enclosing axis-aligned rectangle', () => {
    const corners = [
      { x: 10, y: 20 },
      { x: 110, y: 25 },
      { x: 105, y: 165 },
      { x: 15, y: 160 },
    ];

    expect(boundsFromCorners(corners)).toEqual({
      x: 10,
      y: 20,
      width: 100,
      height: 145,
    });
  });
});

describe('isValidCardQuad', () => {
  it('accepts a convex card-shaped quad', () => {
    const corners = [
      { x: 0, y: 0 },
      { x: 50, y: 0 },
      { x: 50, y: 70 },
      { x: 0, y: 70 },
    ];
    expect(isValidCardQuad(corners)).toBe(true);
  });

  it('rejects a quad with implausible aspect ratio', () => {
    const corners = [
      { x: 0, y: 0 },
      { x: 200, y: 0 },
      { x: 200, y: 70 },
      { x: 0, y: 70 },
    ];
    expect(isValidCardQuad(corners)).toBe(false);
  });
});

describe('computeHomography', () => {
  it('maps source corners to the destination rectangle', () => {
    const src = [
      { x: 0, y: 0 },
      { x: 100, y: 0 },
      { x: 100, y: 140 },
      { x: 0, y: 140 },
    ];
    const matrix = computeHomography(src, 200, 280);

    const mappedTopLeft = applyForward(matrix, 0, 0);
    expect(mappedTopLeft.x).toBeCloseTo(0, 4);
    expect(mappedTopLeft.y).toBeCloseTo(0, 4);

    const mappedBottomRight = applyForward(matrix, 100, 140);
    expect(mappedBottomRight.x).toBeCloseTo(200, 4);
    expect(mappedBottomRight.y).toBeCloseTo(280, 4);
  });
});

function applyForward(matrix, x, y) {
  const denom = matrix[2][0] * x + matrix[2][1] * y + matrix[2][2];
  return {
    x: (matrix[0][0] * x + matrix[0][1] * y + matrix[0][2]) / denom,
    y: (matrix[1][0] * x + matrix[1][1] * y + matrix[1][2]) / denom,
  };
}
