import { describe, expect, mock, test } from 'bun:test'

import { makeImageFillLocalMatrix } from '#core/canvas/fills'
import type { SkiaRenderer } from '#core/canvas/renderer'
import type { Fill, SceneNode } from '#core/scene-graph'

function createRenderer() {
  return {
    ck: {
      Matrix: {
        identity: mock(() => ['identity']),
        invert: mock((matrix) => ['invert', matrix]),
        multiply: mock((...matrices) => ['multiply', ...matrices]),
        scaled: mock((x, y) => ['scaled', x, y]),
        translated: mock((x, y) => ['translated', x, y])
      }
    }
  } as SkiaRenderer
}

const node = {
  width: 120,
  height: 80
} as SceneNode

describe('canvas image fills', () => {
  test('keeps untransformed tile fills in image pixel space', () => {
    const renderer = createRenderer()
    const fill = { type: 'IMAGE', imageScaleMode: 'TILE' } as Fill

    const matrix = makeImageFillLocalMatrix(renderer, fill, node, 24, 16)

    expect(matrix).toEqual(['identity'])
    expect(renderer.ck.Matrix.identity).toHaveBeenCalled()
    expect(renderer.ck.Matrix.scaled).not.toHaveBeenCalled()
  })

  test('uses the full imported affine transform for patterned image fills', () => {
    const renderer = createRenderer()
    const transform = { m00: 0.5, m01: 0.1, m02: 0.25, m10: -0.2, m11: 0.25, m12: 0.5 }
    const fill = {
      type: 'IMAGE',
      imageScaleMode: 'TILE',
      imageTransform: transform
    } as Fill

    const matrix = makeImageFillLocalMatrix(renderer, fill, node, 40, 40)

    expect(renderer.ck.Matrix.invert).toHaveBeenCalledWith([
      0.5, 0.1, 0.25, -0.2, 0.25, 0.5, 0, 0, 1
    ])
    expect(matrix).toEqual([
      'multiply',
      ['scaled', 120, 80],
      ['invert', [0.5, 0.1, 0.25, -0.2, 0.25, 0.5, 0, 0, 1]],
      ['scaled', 0.025, 0.025]
    ])
  })
})
