import { describe, expect, it } from 'vitest'
import type { CaseState, DocumentExhibit, NoteExhibit } from '../src/types.js'
import { filterLevelVisibility, mergePlayerStateForPersistence } from './levelVisibility.js'

const placed = { x: 10, y: 20, width: 174, height: 145, rotation: 0, zIndex: 1, hidden: false }
const open: DocumentExhibit = { id: 'open', type: 'document', title: 'Open', body: [], regions: [], fileType: 'image', captureKind:'unclassified',metadata: {}, ...placed }
const gated: DocumentExhibit = { id: 'gated', type: 'document', title: 'Gated', body: [], regions: [], fileType: 'image', captureKind:'unclassified',metadata: {}, requiredFlags: ['tip.received'], ...placed }
const note: NoteExhibit = { id:'note',type:'note',title:'Note',content:'',presentation:'luggage',...placed }
const state: CaseState = {
  id: 'demo', title: 'Demo', subtitle: '', exhibits: [open, gated, note], viewport: { x: 0, y: 0, zoom: 1 },
  relations: [{ id: 'source', type: 'source', fromExhibitId: note.id, toExhibitId: gated.id, sortOrder: 0 }],
  connections: [{ id: 'thread', fromExhibitId: open.id, toExhibitId: gated.id }],
  views: [], brief: { body: '', concepts: [] }, goals: [], revision: 0,
}

describe('level flag visibility', () => {
  it('hides gated documents and every edge touching them', () => {
    const visible = filterLevelVisibility(state, [], [], false)
    expect(visible.exhibits.map(item => item.id)).toEqual(['open', 'note'])
    expect(visible.relations).toEqual([])
    expect(visible.connections).toEqual([])
    expect(visible.newlyVisibleDocumentIds).toEqual(['open'])
  })

  it('reveals earned documents once without leaking their gate definition', () => {
    const visible = filterLevelVisibility(state, ['tip.received'], ['open'], false)
    expect(visible.exhibits.map(item => item.id)).toEqual(['open', 'gated', 'note'])
    expect((visible.exhibits[1] as DocumentExhibit).requiredFlags).toBeUndefined()
    expect(visible.newlyVisibleDocumentIds).toEqual(['gated'])
  })

  it('returns all documents and requirements to author mode', () => {
    const authored = filterLevelVisibility(state, [], [], true)
    expect((authored.exhibits[1] as DocumentExhibit).requiredFlags).toEqual(['tip.received'])
    expect(authored.newlyVisibleDocumentIds).toEqual([])
  })

  it('preserves unrevealed documents and their edges during a play-mode save', () => {
    const visible = filterLevelVisibility(state, [], ['open'], false)
    const submitted = { ...visible, exhibits: visible.exhibits.map(item => item.id === 'open' ? { ...item, x: 99 } : item) }
    const merged = mergePlayerStateForPersistence(state, visible, submitted)
    expect(merged.exhibits.find(item => item.id === 'open')?.x).toBe(99)
    expect(merged.exhibits.find(item => item.id === 'gated')).toMatchObject({ requiredFlags: ['tip.received'] })
    expect(merged.relations).toHaveLength(1)
    expect(merged.connections).toHaveLength(1)
  })
})
