import { useMemo } from 'react';
import { useLocation } from 'react-router-dom';
import MiniSearch from 'minisearch';
import { commandRegistry } from './registry';
import type { CommandItem } from './types';
import type { UserRole } from '@/types/api';
import { useSettingsStore } from '@/stores/settings.store';
import { useAuthStore } from '@/stores/auth.store';
import { getUserRoles, hasAnyRole } from '@/utils/roles';

interface IndexedItem extends CommandItem {
  keywordsJoined: string;
}

/** Map current path prefixes to the command groups they relate to */
const CONTEXT_PREFIXES: Record<string, string[]> = {
  '/app/campaigns': ['Advocacy'],
  '/app/campaign-moderation': ['Advocacy'],
  '/app/representatives': ['Advocacy'],
  '/app/email-queue': ['Advocacy'],
  '/app/responses': ['Advocacy'],
  '/app/influence': ['Advocacy'],
  '/app/sms': ['Broadcast'],
  '/app/listmonk': ['Broadcast'],
  '/app/email-templates': ['Broadcast'],
  '/app/map': ['Map'],
  '/app/media': ['Media'],
  '/app/pages': ['Web'],
  '/app/docs': ['Web'],
  '/app/code': ['Web'],
  '/app/navigation': ['Web'],
  '/app/payments': ['Payments'],
  '/app/social': ['Social'],
  '/app/services': ['Services'],
  '/app/tunnel': ['Services'],
  '/app/observability': ['Services'],
  '/app/settings': ['Settings'],
  '/app/users': ['People & Access'],
  '/app/people': ['People & Access'],
};

/**
 * Builds a MiniSearch index from the command registry,
 * filtered by the current user's roles and enabled feature flags.
 */
export function useCommandIndex() {
  const { settings } = useSettingsStore();
  const { user } = useAuthStore();
  const location = useLocation();

  const { search, allItems } = useMemo(() => {
    const userRoles = user ? getUserRoles(user) : [];
    const isSuperAdmin = userRoles.includes('SUPER_ADMIN');

    // Feature flag resolution — matches logic in AppLayout.tsx
    const featureEnabled = (flag: string | undefined): boolean => {
      if (!flag) return true;
      if (!settings) return true; // show all when settings haven't loaded
      const value = (settings as unknown as Record<string, unknown>)[flag];
      // Flags that default to false — only show when explicitly enabled
      const defaultsOff = ['enablePayments', 'enableSms', 'enablePeople', 'enableSocial', 'enableChat', 'enableMeet'];
      if (defaultsOff.includes(flag)) return value === true;
      return value !== false;
    };

    // Filter registry by role + feature flags
    const filtered = commandRegistry.filter((item) => {
      if (!featureEnabled(item.featureFlag)) return false;
      if (item.requiredRoles && item.requiredRoles.length > 0) {
        // SUPER_ADMIN can see everything
        if (isSuperAdmin) return true;
        if (!hasAnyRole(user, item.requiredRoles as UserRole[])) return false;
      }
      return true;
    });

    // Build index
    const indexed: IndexedItem[] = filtered.map((item) => ({
      ...item,
      keywordsJoined: item.keywords.join(' '),
    }));

    const idx = new MiniSearch<IndexedItem>({
      fields: ['title', 'keywordsJoined', 'group'],
      storeFields: ['id'],
      idField: 'id',
      searchOptions: {
        boost: { title: 10, keywordsJoined: 3, group: 1 },
        prefix: true,
        // Only allow fuzzy matching for terms 5+ chars to prevent
        // false positives like "test" → "text"
        fuzzy: (term) => (term.length >= 5 ? 0.2 : false),
      },
    });

    idx.addAll(indexed);

    // Create lookup map for fast retrieval
    const itemMap = new Map(filtered.map((item) => [item.id, item]));

    // Resolve contextual groups from current path
    const currentPath = location.pathname;
    const contextGroups: string[] = [];
    if (currentPath !== '/app') {
      for (const [prefix, groups] of Object.entries(CONTEXT_PREFIXES)) {
        if (currentPath.startsWith(prefix)) {
          contextGroups.push(...groups);
          break;
        }
      }
    }

    const searchFn = (query: string, scopeGroups?: string[]): CommandItem[] => {
      if (!query || query.length < 1) return [];
      const results = idx.search(query);

      // Map to items with scores
      const scored = results
        .map((r) => {
          const item = itemMap.get(r.id as string);
          if (!item) return null;

          // Apply scope filter: skip items not in scope groups
          if (scopeGroups && scopeGroups.length > 0) {
            if (!scopeGroups.includes(item.group)) return null;
          }

          // Apply contextual boost
          let boostedScore = r.score;
          if (contextGroups.length > 0) {
            if (currentPath.startsWith(item.path) && item.path !== '/app') {
              boostedScore += 50;
            } else if (contextGroups.includes(item.group)) {
              boostedScore += 25;
            }
          }

          return { item, score: boostedScore };
        })
        .filter((entry): entry is { item: CommandItem; score: number } => !!entry);

      // Re-sort by boosted score (descending)
      scored.sort((a, b) => b.score - a.score);

      return scored.map((s) => s.item);
    };

    return { search: searchFn, allItems: filtered };
  }, [settings, user, location.pathname]);

  return { search, allItems };
}
