/**
 * useNaturalLanguageFilters Hook
 *
 * Convert natural language queries to structured filters
 * Examples:
 * - "red shirts under $50" → color: red, category: shirts, price: <= 50
 * - "size large blue jeans" → size: L, color: blue, category: jeans
 */
import { useMemo, useCallback } from 'react';
import { useSearchState } from './useSearchState';
// Default patterns for parsing natural language
const DEFAULT_PATTERNS = {
    // Price patterns
    price: [
        { pattern: /under\s*\$?(\d+(?:\.\d{2})?)/i, operator: '<=', field: 'price' },
        { pattern: /less than\s*\$?(\d+(?:\.\d{2})?)/i, operator: '<', field: 'price' },
        { pattern: /over\s*\$?(\d+(?:\.\d{2})?)/i, operator: '>=', field: 'price' },
        { pattern: /more than\s*\$?(\d+(?:\.\d{2})?)/i, operator: '>', field: 'price' },
        { pattern: /\$(\d+(?:\.\d{2})?)\s*-\s*\$?(\d+(?:\.\d{2})?)/i, operator: 'range', field: 'price' },
        { pattern: /between\s*\$?(\d+(?:\.\d{2})?)\s*and\s*\$?(\d+(?:\.\d{2})?)/i, operator: 'range', field: 'price' },
        { pattern: /\$(\d+(?:\.\d{2})?)/i, operator: '<=', field: 'price' },
    ],
    // Color patterns
    colors: ['red', 'blue', 'green', 'black', 'white', 'pink', 'purple', 'yellow', 'orange', 'brown', 'gray', 'grey', 'navy', 'beige', 'gold', 'silver'],
    // Size patterns
    sizes: {
        'extra small': 'XS',
        'xs': 'XS',
        'small': 'S',
        's': 'S',
        'medium': 'M',
        'm': 'M',
        'large': 'L',
        'l': 'L',
        'extra large': 'XL',
        'xl': 'XL',
        'xxl': 'XXL',
        '2xl': 'XXL',
        'xxxl': 'XXXL',
        '3xl': 'XXXL',
    },
    // Brand patterns (common examples)
    brandIndicators: ['by', 'from', 'brand'],
    // Rating patterns
    ratings: [
        { pattern: /(\d+)\s*\+?\s*stars?/i, field: 'rating', operator: '>=' },
        { pattern: /rated\s*(\d+)/i, field: 'rating', operator: '>=' },
        { pattern: /top\s*rated/i, field: 'rating', value: '4', operator: '>=' },
    ],
    // Availability patterns
    availability: [
        { pattern: /in\s*stock/i, field: 'inStock', value: 'true' },
        { pattern: /available/i, field: 'inStock', value: 'true' },
        { pattern: /on\s*sale/i, field: 'onSale', value: 'true' },
    ],
};
export function useNaturalLanguageFilters(options = {}) {
    const { fieldMappings = {}, valueMappings = {}, autoApply = false, currencySymbol = '$', } = options;
    const { addRefinement, removeRefinement, clearRefinements, setQuery } = useSearchState();
    // Merge default patterns with custom mappings
    const patterns = useMemo(() => ({
        ...DEFAULT_PATTERNS,
        colors: [...DEFAULT_PATTERNS.colors, ...(valueMappings.color ? Object.keys(valueMappings.color) : [])],
        sizes: { ...DEFAULT_PATTERNS.sizes, ...(valueMappings.size || {}) },
    }), [valueMappings]);
    const parse = useCallback((query) => {
        const filters = [];
        let cleanedQuery = query;
        // Parse price filters
        for (const pricePattern of patterns.price) {
            const match = query.match(pricePattern.pattern);
            if (match) {
                if (pricePattern.operator === 'range' && match[2]) {
                    // Handle price range
                    filters.push({
                        field: fieldMappings.price || 'price',
                        value: `>=${match[1]}`,
                        operator: '>=',
                        confidence: 0.95,
                        matchedText: match[0],
                    });
                    filters.push({
                        field: fieldMappings.price || 'price',
                        value: `<=${match[2]}`,
                        operator: '<=',
                        confidence: 0.95,
                        matchedText: match[0],
                    });
                }
                else if (match[1]) {
                    filters.push({
                        field: fieldMappings.price || 'price',
                        value: `${pricePattern.operator}${match[1]}`,
                        operator: pricePattern.operator,
                        confidence: 0.95,
                        matchedText: match[0],
                    });
                }
                cleanedQuery = cleanedQuery.replace(match[0], ' ');
                break; // Only match first price pattern
            }
        }
        // Parse colors
        const colorRegex = new RegExp(`\\b(${patterns.colors.join('|')})\\b`, 'gi');
        const colorMatches = query.match(colorRegex);
        if (colorMatches) {
            colorMatches.forEach(color => {
                const normalizedColor = valueMappings.color?.[color.toLowerCase()] || color.toLowerCase();
                filters.push({
                    field: fieldMappings.color || 'color',
                    value: normalizedColor,
                    operator: '=',
                    confidence: 0.9,
                    matchedText: color,
                });
                cleanedQuery = cleanedQuery.replace(new RegExp(`\\b${color}\\b`, 'gi'), ' ');
            });
        }
        // Parse sizes
        const sizeEntries = Object.entries(patterns.sizes);
        for (const [sizeText, sizeValue] of sizeEntries) {
            const sizeRegex = new RegExp(`\\b${sizeText}\\b`, 'gi');
            if (sizeRegex.test(query)) {
                filters.push({
                    field: fieldMappings.size || 'size',
                    value: sizeValue,
                    operator: '=',
                    confidence: 0.85,
                    matchedText: sizeText,
                });
                cleanedQuery = cleanedQuery.replace(sizeRegex, ' ');
                break; // Only match first size
            }
        }
        // Parse ratings
        for (const ratingPattern of patterns.ratings) {
            if ('value' in ratingPattern) {
                if (ratingPattern.pattern.test(query)) {
                    filters.push({
                        field: fieldMappings.rating || ratingPattern.field,
                        value: `${ratingPattern.operator}${ratingPattern.value}`,
                        operator: ratingPattern.operator,
                        confidence: 0.8,
                        matchedText: query.match(ratingPattern.pattern)?.[0] || '',
                    });
                    cleanedQuery = cleanedQuery.replace(ratingPattern.pattern, ' ');
                }
            }
            else {
                const match = query.match(ratingPattern.pattern);
                if (match && match[1]) {
                    filters.push({
                        field: fieldMappings.rating || ratingPattern.field,
                        value: `${ratingPattern.operator}${match[1]}`,
                        operator: ratingPattern.operator,
                        confidence: 0.85,
                        matchedText: match[0],
                    });
                    cleanedQuery = cleanedQuery.replace(match[0], ' ');
                }
            }
        }
        // Parse availability
        for (const availPattern of patterns.availability) {
            if (availPattern.pattern.test(query)) {
                filters.push({
                    field: fieldMappings[availPattern.field] || availPattern.field,
                    value: availPattern.value,
                    operator: '=',
                    confidence: 0.9,
                    matchedText: query.match(availPattern.pattern)?.[0] || '',
                });
                cleanedQuery = cleanedQuery.replace(availPattern.pattern, ' ');
            }
        }
        // Clean up the query
        cleanedQuery = cleanedQuery
            .replace(/\s+/g, ' ')
            .trim();
        return {
            cleanedQuery,
            filters,
            originalQuery: query,
            hasFilters: filters.length > 0,
        };
    }, [patterns, fieldMappings, valueMappings]);
    const applyFilters = useCallback((filters) => {
        filters.forEach(filter => {
            addRefinement(filter.field, filter.value, false);
        });
        // Trigger search after all filters are added
        if (filters.length > 0) {
            // The last addRefinement with triggerSearch=true would be called
            // But we add them all with false and rely on the query change to trigger
        }
    }, [addRefinement]);
    const parseAndApply = useCallback((query) => {
        const result = parse(query);
        if (result.hasFilters) {
            applyFilters(result.filters);
            // Update the query to the cleaned version
            if (result.cleanedQuery !== query) {
                setQuery(result.cleanedQuery, true);
            }
        }
        return result;
    }, [parse, applyFilters, setQuery]);
    return {
        parse,
        applyFilters,
        parseAndApply,
    };
}
/**
 * Utility to format parsed filters for display
 */
export function formatParsedFilters(filters) {
    return filters
        .map(f => `${f.field}: ${f.value}`)
        .join(', ');
}
