import Fuse from 'fuse.js'

class FuzzySearchEngine {
  constructor() {
    this.fuseInstance = null
    this.currentDocuments = []
    this.fuseConfig = {
      threshold: 0.6,
      distance: 100,
      includeScore: true,
      includeMatches: true,
      minMatchCharLength: 2,
      tokenize: true,
      tokenSeparator: /[\s\p{P}\u3000-\u303f\uff00-\uffef]+/u,
      keys: ['text']
    }
    console.log('🔍 FuzzySearchEngine: initialized with optimized Chinese configuration')
  }

  initIndex(documents) {
    try {
      if (!Array.isArray(documents)) {
        console.error('❌ FuzzySearchEngine.initIndex: documents must be an array')
        return false
      }

      const validDocuments = documents.filter(doc =>
        doc && doc.text && typeof doc.text === 'string' && doc.text.trim().length > 0
      )

      if (validDocuments.length === 0) {
        console.warn('⚠️ FuzzySearchEngine.initIndex: no valid documents after filtering')
        this.fuseInstance = null
        this.currentDocuments = []
        return false
      }

      this.fuseInstance = new Fuse(validDocuments, this.fuseConfig)
      this.currentDocuments = validDocuments

      console.log(`✅ FuzzySearchEngine.initIndex: index built successfully with ${validDocuments.length} documents`)
      return true

    } catch (error) {
      console.error('❌ FuzzySearchEngine.initIndex: failed to initialize index', error)
      this.fuseInstance = null
      this.currentDocuments = []
      return false
    }
  }

  preprocessKeyword(keyword) {
    try {
      if (!keyword || typeof keyword !== 'string') {
        return ''
      }

      let processed = keyword

      processed = processed.replace(/\s+/g, ' ')

      processed = processed.replace(/[""''【】《》（）「」『』〔〕［］｛｝〈〉]/g, '')

      processed = processed.replace(/[…—～－]/g, ' ')

      processed = processed.replace(/[。，、；：？！""''【】《》（）「」『』〔〕［］｛｝〈〉·…—～－]/g, ' ')

      processed = processed.replace(/\s{2,}/g, ' ').trim()

      if (processed.length > 200) {
        processed = processed.substring(0, 200)
      }

      return processed

    } catch (error) {
      console.error('❌ FuzzySearchEngine.preprocessKeyword: error preprocessing keyword', error)
      return keyword || ''
    }
  }

  search(keyword, options = {}) {
    try {
      if (!keyword || typeof keyword !== 'string') {
        console.warn('⚠️ FuzzySearchEngine.search: keyword is required and must be a string')
        return []
      }

      if (keyword.trim().length < 2) {
        console.warn('⚠️ FuzzySearchEngine.search: keyword must be at least 2 characters')
        return []
      }

      if (!this.isReady()) {
        console.error('❌ FuzzySearchEngine.search: engine is not ready, call initIndex first')
        return []
      }

      const processedKeyword = this.preprocessKeyword(keyword)

      if (!processedKeyword || processedKeyword.length < 2) {
        console.warn('⚠️ FuzzySearchEngine.search: preprocessed keyword is too short')
        return []
      }

      const limit = options.limit || 20

      console.log(`🔍 FuzzySearchEngine.search: searching for "${processedKeyword}" (limit: ${limit})`)

      const startTime = performance.now()
      const rawResults = this.fuseInstance.search(processedKeyword, { limit })
      const endTime = performance.now()
      const searchTime = endTime - startTime

      console.log(`📊 FuzzySearchEngine.search: found ${rawResults.length} results in ${searchTime.toFixed(2)}ms`)

      if (rawResults.length > 0) {
        const top3 = rawResults.slice(0, 3)
        top3.forEach((result, idx) => {
          const score = result.score !== undefined ? result.score : 'N/A'
          const preview = result.item?.text?.substring(0, 50) || 'N/A'
          console.log(`   ${idx + 1}. Score: ${score?.toFixed(4)} | Preview: ${preview}...`)
        })
      }

      const formattedResults = rawResults.map((rawResult, index) => 
        this.formatResult(rawResult, index)
      )

      console.log(`✅ FuzzySearchEngine.search: returned ${formattedResults.length} formatted results`)
      return formattedResults

    } catch (error) {
      console.error('❌ FuzzySearchEngine.search: search failed', error)
      return []
    }
  }

  formatResult(rawResult, index) {
    try {
      if (!rawResult || !rawResult.item) {
        console.warn('⚠️ FuzzySearchEngine.formatResult: invalid raw result')
        return null
      }

      const item = rawResult.item
      const text = item.text || ''
      const fuseScore = rawResult.score
      const matches = rawResult.matches || []

      const randomSuffix = Math.random().toString(36).substring(2, 8)
      const uniqueId = `search_${Date.now()}_${index}_${randomSuffix}`

      let matchedText = ''
      let startOffset = -1
      let endOffset = -1

      if (matches.length > 0 && matches[0].indices && matches[0].indices.length > 0) {
        const textMatches = matches.filter(m => m.key === 'text')

        if (textMatches.length > 0) {
          const allIndices = textMatches.flatMap(m => m.indices || [])
          
          if (allIndices.length > 0) {
            allIndices.sort((a, b) => a[0] - b[0])
            
            startOffset = Math.max(0, allIndices[0][0])
            const lastMatch = allIndices[allIndices.length - 1]
            endOffset = Math.min(text.length, lastMatch[1] + 1)

            if (startOffset < text.length && endOffset <= text.length && startOffset < endOffset) {
              matchedText = text.substring(startOffset, endOffset)
            }
          }
        }
      }

      if (!matchedText && text.length > 0) {
        matchedText = text.substring(0, Math.min(100, text.length))
        startOffset = 0
        endOffset = matchedText.length
      }

      const contextStart = Math.max(0, startOffset - 50)
      const contextEnd = Math.min(text.length, endOffset + 50)
      const context = text.substring(contextStart, contextEnd)

      const location = {
        startOffset: startOffset,
        endOffset: endOffset,
        originalLocation: item.location || null
      }

      const similarityScore = fuseScore !== undefined ? 1 - fuseScore : 0

      const formattedResult = {
        id: uniqueId,
        text: text,
        matchedText: matchedText,
        score: similarityScore,
        fuseScore: fuseScore,
        context: context,
        location: location,
        matches: matches,
        originalData: {
          type: item.type || 'unknown',
          location: item.location || null,
          element: item.element || null,
          page: item.page || null
        },
        metadata: {
          searchIndex: index,
          timestamp: Date.now(),
          keywordLength: matchedText.length
        }
      }

      return formattedResult

    } catch (error) {
      console.error(`❌ FuzzySearchEngine.formatResult: error formatting result at index ${index}`, error)
      return null
    }
  }

  getStats() {
    try {
      return {
        isReady: this.isReady(),
        documentCount: this.currentDocuments.length,
        config: { ...this.fuseConfig },
        lastUpdated: this.currentDocuments.length > 0 ? new Date().toISOString() : null
      }
    } catch (error) {
      console.error('❌ FuzzySearchEngine.getStats: error getting stats', error)
      return {
        isReady: false,
        documentCount: 0,
        config: {},
        lastUpdated: null,
        error: error.message
      }
    }
  }

  clear() {
    try {
      this.fuseInstance = null
      this.currentDocuments = []

      console.log('✅ FuzzySearchEngine.clear: index and documents cleared')
      return true

    } catch (error) {
      console.error('❌ FuzzySearchEngine.clear: error clearing engine', error)
      return false
    }
  }

  isReady() {
    try {
      return this.fuseInstance !== null && this.currentDocuments.length > 0
    } catch (error) {
      console.error('❌ FuzzySearchEngine.isReady: error checking readiness', error)
      return false
    }
  }
}

export default new FuzzySearchEngine()
