/**
 * Metadata cold-read guard (verifyMetadataLive) — a downstream deployment
 * reported cold `find({ where })` returning a silent `[]` on a freshly-opened
 * brain (a native metadata index that reports data but has not loaded its field
 * postings). This guard, the field-index counterpart of verifyGraphAdjacencyLive,
 * probes a known persisted value on the first filtered find(): if the index does
 * not serve it, brainy rebuilds and re-probes, and raises a loud
 * MetadataIndexNotReadyError only if the rebuild still can't serve — never a
 * silent empty result that misrepresents existing data.
 *
 * The 8.0 JS index cold-loads correctly, so we simulate the cold native failure
 * mode by intercepting the provider's getIdsForFilter/rebuild.
 */
import { describe, it, expect, beforeEach } from 'vitest'
import { Brainy, NounType, MetadataIndexNotReadyError } from '../../src/index.js'

const V = () => Array.from({ length: 384 }, (_, i) => Math.sin(i * 0.1) + 0.001)

describe('Metadata cold-read guard (#venue silent-[])', () => {
  let brain: any

  beforeEach(async () => {
    brain = new Brainy({ requireSubtype: false, storage: { type: 'memory' } })
    await brain.init()
    await brain.add({ vector: V(), type: NounType.Concept, metadata: { status: 'active' } })
    await brain.add({ vector: V(), type: NounType.Concept, metadata: { status: 'archived' } })
    await brain.flush()
  })

  it('warm brain: filtered find is correct and the guard does not rebuild', async () => {
    const mi = brain.metadataIndex
    let rebuilds = 0
    const origRebuild = mi.rebuild.bind(mi)
    mi.rebuild = async () => {
      rebuilds++
      return origRebuild()
    }
    const res = await brain.find({ where: { status: 'active' }, limit: 100 })
    expect(res.length).toBe(1)
    expect(rebuilds).toBe(0) // served live — no rebuild
    expect(brain._metadataVerified).toBe(true) // one-shot latched
    mi.rebuild = origRebuild
  })

  it('cold index: verifyMetadataLive self-heals via rebuild — find({where}) is correct, NOT silent []', async () => {
    const mi = brain.metadataIndex
    const origGetIds = mi.getIdsForFilter.bind(mi)
    const origRebuild = mi.rebuild.bind(mi)
    let cold = true
    brain._metadataVerified = false // re-arm the one-shot for this scenario
    mi.getIdsForFilter = async (...a: any[]) => (cold ? [] : origGetIds(...a))
    mi.rebuild = async () => {
      await origRebuild()
      cold = false // the rebuild warms the postings
    }
    try {
      const res = await brain.find({ where: { status: 'active' }, limit: 100 })
      expect(res.length).toBe(1) // self-healed — the known entity is returned
    } finally {
      mi.getIdsForFilter = origGetIds
      mi.rebuild = origRebuild
    }
  })

  it('unrecoverably cold index: find({where}) throws MetadataIndexNotReadyError — never a silent []', async () => {
    const mi = brain.metadataIndex
    const origGetIds = mi.getIdsForFilter.bind(mi)
    const origRebuild = mi.rebuild.bind(mi)
    brain._metadataVerified = false
    mi.getIdsForFilter = async () => [] // always cold; rebuild can't fix it
    mi.rebuild = async () => {}
    try {
      await expect(brain.find({ where: { status: 'active' }, limit: 100 })).rejects.toBeInstanceOf(
        MetadataIndexNotReadyError
      )
    } finally {
      mi.getIdsForFilter = origGetIds
      mi.rebuild = origRebuild
    }
  })

  it('a query with no filter does not trigger the metadata probe', async () => {
    const mi = brain.metadataIndex
    let probes = 0
    const origGetIds = mi.getIdsForFilter.bind(mi)
    mi.getIdsForFilter = async (...a: any[]) => {
      probes++
      return origGetIds(...a)
    }
    brain._metadataVerified = false
    // A pure vector query (no where/type) must not run verifyMetadataLive's probe.
    await brain.find({ vector: V(), limit: 5 })
    expect(brain._metadataVerified).toBe(false) // guard never ran
    mi.getIdsForFilter = origGetIds
    void probes
  })
})
