/**
 * VFS mkdir() Bug Fix Test (v6.2.9)
 *
 * Tests for the bug where vfs.mkdir() caused previously created directories
 * to disappear from vfs.readdir('/').
 *
 * Root cause: The verbCountsByType optimization skipped verb types with count 0,
 * which could happen when statistics were stale after restart.
 *
 * Fix:
 * 1. Option A: Never skip a verb type that's explicitly requested in the filter
 * 2. Option B: Added fast path for sourceId + verbType combo (common VFS pattern)
 *
 * Originally reported by a downstream application using the VFS.
 */

import { describe, it, expect, beforeEach, afterEach } from 'vitest'
import { Brainy, VerbType } from '../../../src/index.js'

describe('VFS mkdir() Bug Fix (v6.2.9)', () => {
  let brain: Brainy

  beforeEach(async () => {
    brain = new Brainy({ requireSubtype: false,
      storage: { type: 'memory' }
    })
    await brain.init()
  })

  afterEach(async () => {
    await brain.close()
  })

  describe('mkdir() should not corrupt VFS index', () => {
    it('should show all directories after mkdir() is called', async () => {
      const vfs = brain.vfs
      await vfs.init()

      // Step 1: Create directory via writeFile (auto-creates parent directories)
      await vfs.writeFile('/Personas/user.md', 'content')
      console.log('Created /Personas/user.md')

      // Verify /Personas is visible
      const entries1 = await vfs.readdir('/', { withFileTypes: true })
      const names1 = entries1.map((e: any) => e.name)
      console.log('After writeFile - root entries:', names1)
      expect(names1).toContain('Personas')

      // Step 2: Create another directory via mkdir
      await vfs.mkdir('/apps/my-app', { recursive: true })
      console.log('Created /apps/my-app')

      // Step 3: Verify BOTH directories are visible (THIS IS THE BUG)
      const entries2 = await vfs.readdir('/', { withFileTypes: true })
      const names2 = entries2.map((e: any) => e.name)
      console.log('After mkdir - root entries:', names2)

      // This assertion failed before the fix
      expect(names2).toContain('Personas')
      expect(names2).toContain('apps')
      expect(names2.length).toBe(2)
    })

    it('should handle multiple nested directories', async () => {
      const vfs = brain.vfs
      await vfs.init()

      // Create multiple directories via different methods
      await vfs.writeFile('/docs/readme.md', 'readme')
      await vfs.mkdir('/config', { recursive: true })
      await vfs.writeFile('/data/users/user1.json', '{}')
      await vfs.mkdir('/logs/archive', { recursive: true })

      // Verify all root directories are visible
      const entries = await vfs.readdir('/', { withFileTypes: true })
      const names = entries.map((e: any) => e.name)
      console.log('All root entries:', names)

      expect(names).toContain('docs')
      expect(names).toContain('config')
      expect(names).toContain('data')
      expect(names).toContain('logs')
      expect(names.length).toBe(4)
    })
  })

  describe('related should query Contains relationships correctly', () => {
    it('should find Contains relationships via sourceId + verbType filter', async () => {
      // Create some entities and relationships
      const parent = await brain.add({
        data: 'Parent entity',
        type: 'collection',
        metadata: { name: 'parent' }
      })

      const child1 = await brain.add({
        data: 'Child 1',
        type: 'document',
        metadata: { name: 'child1' }
      })

      const child2 = await brain.add({
        data: 'Child 2',
        type: 'document',
        metadata: { name: 'child2' }
      })

      // Create Contains relationships
      await brain.relate({ from: parent, to: child1, type: VerbType.Contains })
      await brain.relate({ from: parent, to: child2, type: VerbType.Contains })

      // Query relationships (this is what getChildren() does)
      const relations = await brain.related({
        from: parent,
        type: VerbType.Contains
      })

      console.log('Relations found:', relations.length)
      expect(relations.length).toBe(2)
      expect(relations.map(r => r.to)).toContain(child1)
      expect(relations.map(r => r.to)).toContain(child2)
    })

    it('should return relationships even with mixed verb types', async () => {
      // Create entities
      const entityA = await brain.add({ data: 'Entity A', type: 'concept' })
      const entityB = await brain.add({ data: 'Entity B', type: 'concept' })
      const entityC = await brain.add({ data: 'Entity C', type: 'concept' })

      // Create different types of relationships
      await brain.relate({ from: entityA, to: entityB, type: VerbType.Contains })
      await brain.relate({ from: entityA, to: entityC, type: VerbType.RelatedTo })

      // Query only Contains relationships
      const containsRelations = await brain.related({
        from: entityA,
        type: VerbType.Contains
      })

      expect(containsRelations.length).toBe(1)
      expect(containsRelations[0].to).toBe(entityB)

      // Query only RelatedTo relationships
      const relatedRelations = await brain.related({
        from: entityA,
        type: VerbType.RelatedTo
      })

      expect(relatedRelations.length).toBe(1)
      expect(relatedRelations[0].to).toBe(entityC)
    })
  })

  describe('Fast path for sourceId + verbType filter', () => {
    it('should use fast path for VFS-style queries', async () => {
      // Create parent and children
      const parent = await brain.add({
        data: 'Parent',
        type: 'collection',
        metadata: { name: 'parent' }
      })

      // Create many children to verify performance
      const children: string[] = []
      for (let i = 0; i < 10; i++) {
        const child = await brain.add({
          data: `Child ${i}`,
          type: 'document',
          metadata: { name: `child${i}` }
        })
        children.push(child)
        await brain.relate({ from: parent, to: child, type: VerbType.Contains })
      }

      // Query should use the new fast path
      const startTime = performance.now()
      const relations = await brain.related({
        from: parent,
        type: VerbType.Contains
      })
      const elapsed = performance.now() - startTime

      console.log(`Query returned ${relations.length} relations in ${elapsed.toFixed(2)}ms`)
      expect(relations.length).toBe(10)

      // Verify all children are found
      for (const child of children) {
        expect(relations.map(r => r.to)).toContain(child)
      }
    })
  })

  describe('Delete and recreate folder (v6.2.9 cache invalidation fix)', () => {
    it('should handle delete folder → recreate folder without corruption', async () => {
      const vfs = brain.vfs
      await vfs.init()

      // Step 1: Create a folder with content
      await vfs.mkdir('/test-folder', { recursive: true })
      await vfs.writeFile('/test-folder/file1.txt', 'content1')
      console.log('Created /test-folder with file1.txt')

      // Verify folder exists
      const entries1 = await vfs.readdir('/', { withFileTypes: true })
      expect(entries1.map((e: any) => e.name)).toContain('test-folder')

      // Step 2: Delete the folder
      await vfs.rmdir('/test-folder', { recursive: true })
      console.log('Deleted /test-folder')

      // Verify folder is gone
      const entries2 = await vfs.readdir('/', { withFileTypes: true })
      expect(entries2.map((e: any) => e.name)).not.toContain('test-folder')

      // Step 3: Recreate the folder (THIS IS WHERE THE BUG WAS)
      await vfs.mkdir('/test-folder', { recursive: true })
      console.log('Recreated /test-folder')

      // Step 4: Create new content
      await vfs.writeFile('/test-folder/file2.txt', 'content2')
      console.log('Created /test-folder/file2.txt')

      // Step 5: Verify everything works
      const entries3 = await vfs.readdir('/', { withFileTypes: true })
      expect(entries3.map((e: any) => e.name)).toContain('test-folder')

      const folderContents = await vfs.readdir('/test-folder', { withFileTypes: true })
      expect(folderContents.map((e: any) => e.name)).toContain('file2.txt')
      console.log('Folder recreate test passed!')
    })

    it('should handle multiple delete/recreate cycles', async () => {
      const vfs = brain.vfs
      await vfs.init()

      for (let i = 0; i < 3; i++) {
        // Create
        await vfs.mkdir('/cycle-test', { recursive: true })
        await vfs.writeFile(`/cycle-test/file${i}.txt`, `content${i}`)

        // Verify
        const contents = await vfs.readdir('/cycle-test', { withFileTypes: true })
        expect(contents.length).toBe(1)
        expect(contents[0].name).toBe(`file${i}.txt`)

        // Delete
        await vfs.rmdir('/cycle-test', { recursive: true })

        console.log(`Cycle ${i + 1} completed`)
      }
    })
  })
})
