import { describe, it, expect } from 'vitest'
import { coverScale, clampOffset, sourceSquare } from '../avatar-crop'

describe('coverScale', () => {
  it('scales the smaller dimension to fill a square viewport', () => {
    // landscape 400x200, viewport 100 → height is limiting → scale 0.5
    expect(coverScale(400, 200, 100)).toBeCloseTo(0.5)
    // portrait 200x400 → width limiting → scale 0.5
    expect(coverScale(200, 400, 100)).toBeCloseTo(0.5)
    // square 200x200 → 0.5
    expect(coverScale(200, 200, 100)).toBeCloseTo(0.5)
  })
})

describe('clampOffset', () => {
  it('keeps offset at 0 when the image exactly covers (no slack)', () => {
    // displayed size == viewport → no panning room
    expect(clampOffset(50, 100, 100)).toBe(0)
    expect(clampOffset(-50, 100, 100)).toBe(0)
  })

  it('clamps within the available slack (displayed > viewport)', () => {
    // displayed 160, viewport 100 → slack 60 → max |offset| 30
    expect(clampOffset(100, 160, 100)).toBe(30)
    expect(clampOffset(-100, 160, 100)).toBe(-30)
    expect(clampOffset(10, 160, 100)).toBe(10)
  })
})

describe('sourceSquare', () => {
  it('returns a centered square for a centered, unzoomed cover of a landscape image', () => {
    // 400x200, viewport 100, zoom 1, no offset.
    // cover scale 0.5 → displayed 200x100. The 100x100 viewport maps back to
    // a 200x200 source square centered: sx=100, sy=0, size=200.
    const r = sourceSquare({ imgW: 400, imgH: 200, viewport: 100, zoom: 1, offsetX: 0, offsetY: 0 })
    expect(r.size).toBeCloseTo(200)
    expect(r.sx).toBeCloseTo(100)
    expect(r.sy).toBeCloseTo(0)
  })

  it('shrinks the source square as zoom increases (tighter crop)', () => {
    const z1 = sourceSquare({ imgW: 400, imgH: 200, viewport: 100, zoom: 1, offsetX: 0, offsetY: 0 })
    const z2 = sourceSquare({ imgW: 400, imgH: 200, viewport: 100, zoom: 2, offsetX: 0, offsetY: 0 })
    expect(z2.size).toBeLessThan(z1.size)
    expect(z2.size).toBeCloseTo(100)
  })

  it('never leaves the image bounds (clamped)', () => {
    const r = sourceSquare({
      imgW: 400, imgH: 200, viewport: 100, zoom: 1, offsetX: 9999, offsetY: 9999,
    })
    expect(r.sx).toBeGreaterThanOrEqual(0)
    expect(r.sy).toBeGreaterThanOrEqual(0)
    expect(r.sx + r.size).toBeLessThanOrEqual(400 + 0.001)
    expect(r.sy + r.size).toBeLessThanOrEqual(200 + 0.001)
  })
})
