import { describe, it, expect } from 'vitest'
import {
  DOCUMENT_VERSION,
  ORIENTATIONS,
  BACKGROUNDS,
  DEFAULT_GRID_MM,
  emptyDocument,
  parseDocument,
  pageDimensions,
  backgroundSvg,
  type NoteDocument,
} from '../document'

describe('emptyDocument', () => {
  it('is a single blank A4 portrait page', () => {
    const d = emptyDocument()
    expect(d.version).toBe(DOCUMENT_VERSION)
    expect(d.orientation).toBe('portrait')
    expect(d.background).toBe('blank')
    expect(d.gridMm).toBe(DEFAULT_GRID_MM)
    expect(d.pages).toHaveLength(1)
    expect(d.pages[0].strokes).toEqual([])
  })
})

describe('pageDimensions', () => {
  it('is taller than wide in portrait, wider than tall in landscape', () => {
    const p = pageDimensions('portrait')
    const l = pageDimensions('landscape')
    expect(p.height).toBeGreaterThan(p.width)
    expect(l.width).toBeGreaterThan(l.height)
  })

  it('keeps the A4 aspect ratio (~1.414)', () => {
    const p = pageDimensions('portrait')
    expect(p.height / p.width).toBeCloseTo(297 / 210, 1)
  })
})

describe('parseDocument', () => {
  it('passes through a valid document', () => {
    const doc: NoteDocument = {
      version: DOCUMENT_VERSION,
      orientation: 'landscape',
      background: 'grid',
      gridMm: 5,
      pages: [{ version: 1, strokes: [{ points: [[1, 2, 0.5]] }], texts: [] }],
    }
    expect(parseDocument(doc)).toEqual(doc)
  })

  it('wraps a legacy single-canvas note into a one-page document', () => {
    const legacy = { version: 1, strokes: [{ points: [[3, 4, 0.5]] }] }
    const doc = parseDocument(legacy)
    expect(doc.orientation).toBe('portrait')
    expect(doc.background).toBe('blank')
    expect(doc.pages).toHaveLength(1)
    expect(doc.pages[0].strokes[0].points[0]).toEqual([3, 4, 0.5])
  })

  it('falls back to an empty document for null / garbage', () => {
    expect(parseDocument(null)).toEqual(emptyDocument())
    expect(parseDocument({ foo: 'bar' })).toEqual(emptyDocument())
  })

  it('clamps an out-of-range grid size', () => {
    const huge = parseDocument({ version: 2, orientation: 'portrait', background: 'grid', gridMm: 9999, pages: [] })
    expect(huge.gridMm).toBeLessThanOrEqual(50)
    const tiny = parseDocument({ version: 2, orientation: 'portrait', background: 'grid', gridMm: 0, pages: [] })
    expect(tiny.gridMm).toBeGreaterThan(0)
  })

  it('guarantees at least one page', () => {
    const doc = parseDocument({ version: 2, orientation: 'portrait', background: 'blank', gridMm: 5, pages: [] })
    expect(doc.pages.length).toBeGreaterThanOrEqual(1)
  })

  it('parses a JSON string', () => {
    const doc = parseDocument(JSON.stringify(emptyDocument()))
    expect(doc.pages).toHaveLength(1)
  })
})

describe('backgroundSvg', () => {
  it('returns empty markup for a blank background', () => {
    expect(backgroundSvg('blank', 20, 794, 1123)).toBe('')
  })

  it('renders a repeating pattern for a grid', () => {
    const svg = backgroundSvg('grid', 20, 794, 1123)
    expect(svg).toContain('pattern')
    expect(svg).toContain('20')
  })

  it('renders horizontal lines for a ruled background', () => {
    const svg = backgroundSvg('lines', 20, 794, 1123)
    expect(svg).toContain('pattern')
  })

  it('exposes orientation and background option lists', () => {
    expect(ORIENTATIONS.map((o) => o.value)).toContain('portrait')
    expect(ORIENTATIONS.map((o) => o.value)).toContain('landscape')
    expect(BACKGROUNDS.map((b) => b.value)).toEqual(['blank', 'grid', 'lines'])
  })
})
