// Awesome Bar composable for new frontend
import { ref, computed } from 'vue'
import { useRouter } from 'vue-router'
import { api } from '../api/common'
import { useAuthStore } from '../stores/auth'
import { t } from '../i18n'
import { useDebounceFn } from '@vueuse/core'

interface SearchResult {
  type: string
  label: string
  value: string
  description?: string
  route?: any[]
  onclick?: () => void
  index: number
  match?: string
  image?: string
  recent?: boolean
}

interface SearchResultSet {
  title: string
  results: SearchResult[]
  fetch_type: 'Nav' | 'Global'
}

export function useAwesomeBar() {
  const router = useRouter()
  const authStore = useAuthStore()
  const searchQuery = ref('')
  const searchResults = ref<SearchResultSet[]>([])
  const isLoading = ref(false)
  const showDropdown = ref(false)
  const recentPages = ref<any[]>([])
  
  // Cache for PageTypes list
  const pagetypesCache = ref<string[]>([])
  const pagetypesCacheLoaded = ref(false)
  
  // Load PageTypes from backend
  async function loadPageTypes() {
    if (pagetypesCacheLoaded.value) return
    
    try {
      const response = await api.call('jingrow.client.get_list', {
        pagetype: 'PageType',
        fields: ['name'],
        filters: [],
        order_by: 'name',
        limit_page_length: 999
      })
      
      if (response && response.message) {
        pagetypesCache.value = response.message.map((item: any) => item.name)
        pagetypesCacheLoaded.value = true
      }
    } catch (error) {
      console.error('Awesome Bar - Failed to load PageTypes:', error)
    }
  }
  
  // Initialize - load PageTypes on first use
  loadPageTypes()

  // fuzzy match scoring - supports translation
  // Matches both original (English) and translated text
  function fuzzyMatch(keywords: string, item: string, translateItem = false): { score: number; markedString: string } {
    if (!keywords || !item) {
      return { score: 0, markedString: translateItem ? t(item) : item }
    }

    const lowerKeywords = keywords.toLowerCase()
    
    // Match against original text (English)
    const lowerItemOriginal = item.toLowerCase()
    let scoreOriginal = 0
    let markedStringOriginal = item
    
    // exact match - original
    if (lowerItemOriginal === lowerKeywords) {
      scoreOriginal = 100
      markedStringOriginal = `<mark>${item}</mark>`
    } else if (lowerItemOriginal.startsWith(lowerKeywords)) {
      // starts with - original
      const matched = item.substring(0, keywords.length)
      const rest = item.substring(keywords.length)
      scoreOriginal = 80
      markedStringOriginal = `<mark>${matched}</mark>${rest}`
    } else if (lowerItemOriginal.includes(lowerKeywords)) {
      // contains - original
      const index = lowerItemOriginal.indexOf(lowerKeywords)
      const before = item.substring(0, index)
      const matched = item.substring(index, index + keywords.length)
      const after = item.substring(index + keywords.length)
      scoreOriginal = 60
      markedStringOriginal = `${before}<mark>${matched}</mark>${after}`
    }
    
    // If translation is enabled, also match against translated text
    let scoreTranslated = 0
    let markedStringTranslated = item
    
    if (translateItem) {
      const translatedItem = t(item)
      const lowerItemTranslated = translatedItem.toLowerCase()
      
      // exact match - translated
      if (lowerItemTranslated === lowerKeywords) {
        scoreTranslated = 100
        markedStringTranslated = `<mark>${translatedItem}</mark>`
      } else if (lowerItemTranslated.startsWith(lowerKeywords)) {
        // starts with - translated
        const matched = translatedItem.substring(0, keywords.length)
        const rest = translatedItem.substring(keywords.length)
        scoreTranslated = 80
        markedStringTranslated = `<mark>${matched}</mark>${rest}`
      } else if (lowerItemTranslated.includes(lowerKeywords)) {
        // contains - translated
        const index = lowerItemTranslated.indexOf(lowerKeywords)
        const before = translatedItem.substring(0, index)
        const matched = translatedItem.substring(index, index + keywords.length)
        const after = translatedItem.substring(index + keywords.length)
        scoreTranslated = 60
        markedStringTranslated = `${before}<mark>${matched}</mark>${after}`
      }
    }
    
    // Return the better match (higher score)
    if (scoreTranslated > scoreOriginal) {
      return { score: scoreTranslated, markedString: markedStringTranslated }
    } else {
      return { score: scoreOriginal, markedString: markedStringOriginal }
    }
  }

  // Get recent pages
  function getRecentPages(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    
    // Try to get from authStore first, fallback to window.jingrow.boot
    let recentStr = authStore.user?.recent || '[]'
    
    // Fallback to window.jingrow.boot if authStore is empty
    if (recentStr === '[]' && typeof window !== 'undefined' && (window as any).jingrow?.boot?.user?.recent) {
      recentStr = (window as any).jingrow.boot.user.recent
    }
    
    const recent = JSON.parse(recentStr) || []
    
    recent.forEach((item: any) => {
      const [pagetype, name] = item
      const searchText = `${pagetype} ${name}`
      const match = fuzzyMatch(keywords, searchText)
      
      if (!keywords || match.score > 0) {
        results.push({
          type: 'Recent',
          label: match.markedString || searchText,
          value: searchText,
          route: ['Form', pagetype, name],
          index: match.score + 80,
          recent: true
        })
      }
    })
    
    return results.sort((a, b) => b.index - a.index).slice(0, 5)
  }

  // Get reports - NEW FRONTEND: Reports data will come from global search
  // This function is kept for compatibility but returns empty
  function getReports(keywords: string): SearchResult[] {
    // New frontend architecture: rely on global search API instead of boot data
    return []
  }

  // Get pages (administration/setup pages) - NEW FRONTEND: Pages data will come from global search
  // This function is kept for compatibility but returns empty
  function getPages(keywords: string): SearchResult[] {
    // New frontend architecture: rely on global search API instead of boot data
    return []
  }

  // Get dashboards - NEW FRONTEND: Dashboards data will come from global search
  // This function is kept for compatibility but returns empty
  function getDashboards(keywords: string): SearchResult[] {
    // New frontend architecture: rely on global search API instead of boot data
    return []
  }

  // Get search in list (e.g., "john in User")
  function getSearchInList(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    
    // Check if keywords contain " in "
    if (!keywords.includes(' in ')) return results
    
    const parts = keywords.split(' in ')
    if (parts.length !== 2) return results
    
    const [searchText, pagetype] = parts
    if (!searchText || !pagetype) return results
    
    // Get can_search from permissions
    let canSearch: string[] = authStore.user?.can_search || []
    if (typeof window !== 'undefined' && (window as any).jingrow?.boot?.user?.can_search) {
      canSearch = (window as any).jingrow.boot.user.can_search
    }
    
    // Check if pagetype is in can_search
    const matchedPagetype = canSearch.find(pt => 
      fuzzyMatch(pagetype, pt, true).score > 0
    )
    
    if (matchedPagetype) {
      results.push({
        type: 'In List',
        label: t('Find {0} in {1}', [t(searchText), t(matchedPagetype)]),
        value: t('Find {0} in {1}', [t(searchText), t(matchedPagetype)]),
        route: ['List', matchedPagetype],
        index: fuzzyMatch(pagetype, matchedPagetype, true).score + 1
      })
    }
    
    return results
  }

  // Calculator - evaluate math expressions
  function getCalculator(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    const firstChar = keywords.charAt(0)
    
    // Check if it looks like a math expression
    const isNumber = !isNaN(parseInt(firstChar))
    const isParen = firstChar === '('
    const isEqual = firstChar === '='
    
    if (isNumber || isParen || isEqual) {
      let expr = isEqual ? keywords.substring(1) : keywords
      
      try {
        // Use Function constructor for safe evaluation
        const val = new Function('return ' + expr)()
        
        if (typeof val === 'number' && !isNaN(val)) {
          results.push({
            type: 'Calculator',
            label: `${expr} = <b>${val}</b>`,
            value: `${expr} = ${val}`,
            index: 80,
            onclick: () => {
              // Show result - could use a toast notification
              console.log(`Calculator: ${expr} = ${val}`)
            }
          })
        }
      } catch (e) {
        // Invalid expression, ignore
      }
    }
    
    return results
  }

  // Random password generator
  function getRandom(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    
    if (keywords.toLowerCase().includes('random')) {
      // Generate random string
      const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
      let result = ''
      for (let i = 0; i < 16; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length))
      }
      
      results.push({
        type: 'Random',
        label: t('Generate Random Password'),
        value: result,
        index: 50,
        onclick: () => {
          // Copy to clipboard or show
          navigator.clipboard?.writeText(result)
          console.log('Generated random password:', result)
        }
      })
    }
    
    return results
  }

  // Get help info
  function getHelp(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    
    // Show help when keywords are empty or very short
    if (!keywords || keywords.length < 2) {
      results.push({
        type: 'Help',
        label: t('Search Help'),
        value: 'Help',
        index: -10,
        onclick: () => {
          // Could show a modal with help info
          console.log('Search help: new [type], [type] List, text in [type], #tag, etc.')
        }
      })
    }
    
    return results
  }

  // Get frequent/visited links - NEW FRONTEND: Not implemented yet
  function getFrequentLinks(keywords: string): SearchResult[] {
    // New frontend architecture: this feature is not yet implemented
    return []
  }

  // Tags cache
  const tagsCache = ref<string[]>([])
  const tagsCacheLoaded = ref(false)

  // Fetch tags from backend
  async function fetchTags() {
    if (tagsCacheLoaded.value) return
    
    try {
      const response = await api.call('jingrow.desk.pagetype.tag.tag.get_tags_list_for_awesomebar')
      if (response && response.message) {
        tagsCache.value = response.message
        tagsCacheLoaded.value = true
      }
    } catch (error) {
      console.error('Failed to fetch tags:', error)
    }
  }

  // Get tags (keywords should start with #)
  function getTags(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    
    // Only search tags if keywords start with #
    if (!keywords.startsWith('#')) {
      return results
    }
    
    // Ensure tags are loaded
    fetchTags()
    
    const tagSearch = keywords.slice(1) // Remove #
    
    tagsCache.value.forEach((tag: string) => {
      const match = fuzzyMatch(tagSearch, tag, true)
      
      if (match.score > 0) {
        results.push({
          type: 'Tag',
          label: t('#{0}', [match.markedString || t(tag)]),
          value: t('#{0}', [t(tag)]),
          index: match.score + 1,
          match: tag,
          onclick: () => {
            // Navigate to search results with tag filter
            router.push({
              path: '/search',
              query: { keyword: '#' + tag }
            })
          }
        })
      }
    })
    
    return results.sort((a, b) => b.index - a.index)
  }

  // Get pagetypes
  function getPageTypes(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    
    // Use cached PageTypes list
    let availablePageTypes = pagetypesCache.value
    
    // Try to get permissions from authStore or window.jingrow.boot
    let canRead = authStore.user?.can_read || []
    let canCreate = authStore.user?.can_create || []
    let canSearch = authStore.user?.can_search || []
    
    // Fallback to window.jingrow.boot if authStore is empty
    if (canRead.length === 0 && typeof window !== 'undefined' && (window as any).jingrow?.boot?.user) {
      const bootUser = (window as any).jingrow.boot.user
      canRead = bootUser.can_read || []
      canCreate = bootUser.can_create || []
      canSearch = bootUser.can_search || []
    }
    
    // If still no permissions, use all cached PageTypes
    if (canRead.length === 0 && availablePageTypes.length > 0) {
      canRead = availablePageTypes
      canCreate = availablePageTypes
      canSearch = availablePageTypes
    }
    
    if (canRead.length === 0) {
      return []
    }
    
    canRead.forEach((pagetype: string) => {
      // Use fuzzyMatch with translation enabled (third parameter = true)
      const match = fuzzyMatch(keywords, pagetype, true)
      
      if (match.score > 0) {
        // Create new option - use route instead of onclick for reliable navigation
        if (canCreate.includes(pagetype)) {
          // Generate temp name: new-{pagetype}-{randomStr}
          const randomStr = Math.random().toString(36).substring(2, 12)
          const tempName = `new-${pagetype.toLowerCase().replace(/\s+/g, '-')}-${randomStr}`
          results.push({
            type: 'New',
            label: t('New {0}', [match.markedString]),
            value: t('New {0}', [t(pagetype)]),
            route: ['Form', pagetype, tempName],
            index: match.score + 0.015,
            match: pagetype
          })
        }
        
        // List view
        if (canSearch.includes(pagetype)) {
          results.push({
            type: 'List',
            label: t('{0} List', [match.markedString]),
            value: t('{0} List', [t(pagetype)]),
            route: ['List', pagetype],
            index: match.score + 0.05,
            match: pagetype
          })
        }
      }
    })
    
    return results.sort((a, b) => b.index - a.index)
  }

  // Get workspaces
  function getWorkspaces(keywords: string): SearchResult[] {
    const results: SearchResult[] = []
    const workspaces = authStore.workspaces || []
    
    workspaces.forEach((workspace: any) => {
      const match = fuzzyMatch(keywords, workspace.label || workspace.name)
      
      if (match.score > 0) {
        results.push({
          type: 'Workspace',
          label: `Open ${match.markedString}`,
          value: `Open ${workspace.label || workspace.name}`,
          route: [workspace.name],
          index: match.score
        })
      }
    })
    
    return results.sort((a, b) => b.index - a.index)
  }

  // Get global search results from backend
  async function getGlobalResults(keywords: string, start = 0, limit = 20): Promise<SearchResultSet[]> {
    try {
      const response = await api.call('jingrow.utils.global_search.search', {
        text: keywords,
        start,
        limit
      })
      
      if (response && response.message) {
        const resultSets: Record<string, SearchResult[]> = {}
        
        response.message.forEach((item: any) => {
          if (!resultSets[item.pagetype]) {
            resultSets[item.pagetype] = []
          }
          
          resultSets[item.pagetype].push({
            type: 'Document',
            label: item.name,
            value: item.name,
            description: item.content || '',
            route: ['Form', item.pagetype, item.name],
            index: 50,
            image: item.image
          })
        })
        
        return Object.keys(resultSets).map(pagetype => ({
          title: pagetype,
          results: resultSets[pagetype],
          fetch_type: 'Global' as const
        }))
      }
    } catch (error) {
      console.error('Global search error:', error)
    }
    
    return []
  }

  // Get navigation results (local search)
  function getNavResults(keywords: string): SearchResultSet[] {
    const trimmedKeywords = keywords.toLowerCase().trim()
    
    // Check if this is a tag search (starts with #)
    const isTagSearch = keywords.startsWith('#')
    
    // Get search in list results first if keywords contain " in "
    const searchInListResults = getSearchInList(keywords)
    
    return [
      ...(isTagSearch ? [{
        title: 'Tags',
        fetch_type: 'Nav' as const,
        results: getTags(keywords)
      }] : []),
      {
        title: 'Recents',
        fetch_type: 'Nav' as const,
        results: getRecentPages(keywords)
      },
      {
        title: 'Lists',
        fetch_type: 'Nav' as const,
        results: getPageTypes(keywords).filter(r => r.type === 'List')
      },
      {
        title: 'Create a new ...',
        fetch_type: 'Nav' as const,
        results: getPageTypes(keywords).filter(r => r.type === 'New')
      },
      {
        title: 'Reports',
        fetch_type: 'Nav' as const,
        results: getReports(keywords)
      },
      {
        title: 'Pages',
        fetch_type: 'Nav' as const,
        results: getPages(keywords)
      },
      {
        title: 'Workspace',
        fetch_type: 'Nav' as const,
        results: getWorkspaces(keywords)
      },
      {
        title: 'Dashboards',
        fetch_type: 'Nav' as const,
        results: getDashboards(keywords)
      },
      {
        title: 'Calculator',
        fetch_type: 'Nav' as const,
        results: getCalculator(keywords)
      },
      {
        title: 'Frequent',
        fetch_type: 'Nav' as const,
        results: getFrequentLinks(keywords)
      },
      ...(searchInListResults.length > 0 ? [{
        title: t('Find \'{0}\' in ...', [keywords.split(' in ')[0] || '']),
        fetch_type: 'Nav' as const,
        results: searchInListResults
      }] : [])
    ].filter(set => set.results.length > 0)
  }

  // Main search function
  async function performSearch(keywords: string) {
    if (!keywords || keywords.trim().length < 1) {
      // Show recent pages and frequent links when empty
      searchResults.value = getNavResults('')
      return
    }
    
    isLoading.value = true
    
    try {
      // Get navigation results immediately
      const navResults = getNavResults(keywords)
      searchResults.value = navResults
      
      // Get global results asynchronously
      if (keywords.trim().length >= 2) {
        const globalResults = await getGlobalResults(keywords)
        searchResults.value = [...navResults, ...globalResults]
      }
    } finally {
      isLoading.value = false
    }
  }

  // Handle result click
  function handleResultClick(result: SearchResult) {
    showDropdown.value = false
    
    if (result.onclick) {
      result.onclick()
      return
    }
    
    if (result.route) {
      const [routeType, ...params] = result.route
      
      // Convert pagetype to slug format (kebab-case)
      const toSlug = (str: string) => str.toLowerCase().replace(/\s+/g, '-')
      
      if (routeType === 'Form') {
        const [pagetype, name] = params
        router.push(`/app/${toSlug(pagetype)}/${name}`)
      } else if (routeType === 'List') {
        const [pagetype] = params
        router.push(`/app/${toSlug(pagetype)}`)
      } else if (typeof routeType === 'string' && routeType.startsWith('http')) {
        window.open(routeType, '_blank')
      } else {
        // workspace or custom route
        router.push(`/page/${routeType}`)
      }
    }
  }

  // Handle search input with debounce (modern approach using @vueuse)
  const debouncedSearch = useDebounceFn((value: string) => {
    performSearch(value)
  }, 150)
  
  function handleSearchInput(value: string) {
    searchQuery.value = value
    
    // Immediately show empty state when cleared
    if (!value || value.trim().length === 0) {
      performSearch('')
      return
    }
    
    // Debounced search for non-empty input
    debouncedSearch(value)
  }

  // Clear search
  function clearSearch() {
    searchQuery.value = ''
    searchResults.value = []
    showDropdown.value = false
  }

  return {
    searchQuery,
    searchResults,
    isLoading,
    showDropdown,
    performSearch,
    handleSearchInput,
    handleResultClick,
    clearSearch
  }
}
