#!/usr/bin/env python3
"""Analyze grammar failures in detail."""

import json
import re
from pathlib import Path
from collections import defaultdict
import lark


def main():
    grammar_file = Path(__file__).parent / 'lark_grammars' / 'cypher_from_grammars_v4.lark'
    queries_file = Path(__file__).parent / 'tck-queries' / 'all_queries.json'

    parser = lark.Lark(grammar_file.read_text(), parser='earley')

    with open(queries_file) as f:
        queries = json.load(f)

    # Filter templates
    template_pattern = re.compile(r'<[a-zA-Z_][a-zA-Z0-9_]*>')
    real_queries = [q for q in queries if not template_pattern.search(q.get('query', ''))]

    failures = []
    error_patterns = defaultdict(list)

    for q in real_queries:
        query_text = q.get('query', '')
        if not query_text.strip():
            continue

        try:
            parser.parse(query_text)
        except Exception as e:
            error_str = str(e)

            # Categorize error
            if "No terminal matches" in error_str:
                match = re.search(r"No terminal matches '(.)'", error_str)
                if match:
                    char = match.group(1)
                    error_patterns[f"no_terminal_{char}"].append(query_text)
            elif "Unexpected token" in error_str:
                error_patterns["unexpected_token"].append(query_text)
            else:
                error_patterns["other"].append(query_text)

            failures.append({
                'query': query_text,
                'category': q.get('category', 'unknown'),
                'error': error_str
            })

    print(f"Total failures: {len(failures)}")
    print(f"\nError pattern breakdown:")
    for pattern, queries in sorted(error_patterns.items(), key=lambda x: -len(x[1])):
        print(f"  {pattern}: {len(queries)}")

    print(f"\n{'='*70}")
    print("DETAILED FAILURE ANALYSIS")
    print('='*70)

    # Analyze specific patterns
    for pattern, queries in sorted(error_patterns.items(), key=lambda x: -len(x[1]))[:5]:
        print(f"\n## {pattern} ({len(queries)} failures)")
        print("-" * 50)

        # Show unique query patterns
        seen = set()
        for q in queries[:5]:
            # Normalize
            normalized = ' '.join(q.split()[:20])
            if normalized not in seen:
                seen.add(normalized)
                print(f"\n{q[:200]}...")

    # Identify missing keywords/features
    print(f"\n{'='*70}")
    print("LIKELY MISSING FEATURES")
    print('='*70)

    missing_features = defaultdict(int)
    for f in failures:
        query = f['query'].upper()
        if 'ALL(' in query or 'ANY(' in query or 'NONE(' in query or 'SINGLE(' in query:
            missing_features['list_predicates'] += 1
        if 'FOREACH' in query:
            missing_features['foreach'] += 1
        if 'REDUCE(' in query:
            missing_features['reduce'] += 1
        if 'FILTER(' in query or 'EXTRACT(' in query:
            missing_features['legacy_list_funcs'] += 1
        if re.search(r'\[\s*\w+\s+IN\s+', query):
            missing_features['list_comprehension'] += 1
        if 'EXISTS {' in query or 'EXISTS{' in query:
            missing_features['exists_subquery'] += 1
        if 'COUNT {' in query or 'COUNT{' in query:
            missing_features['count_subquery'] += 1
        if re.search(r'\*\s*\d+\.\.', query) or re.search(r'\*\d+', query):
            missing_features['variable_length_path'] += 1
        if 'USING INDEX' in query or 'USING SCAN' in query:
            missing_features['hints'] += 1
        if 'LOAD CSV' in query:
            missing_features['load_csv'] += 1

    for feature, count in sorted(missing_features.items(), key=lambda x: -x[1]):
        print(f"  {feature}: {count}")

    # Save detailed failures
    output_file = Path(__file__).parent / 'failure_analysis.json'
    with open(output_file, 'w') as f:
        json.dump({
            'total_failures': len(failures),
            'error_patterns': {k: len(v) for k, v in error_patterns.items()},
            'missing_features': dict(missing_features),
            'sample_failures': failures[:50]
        }, f, indent=2)
    print(f"\nDetailed analysis saved to {output_file}")


if __name__ == '__main__':
    main()
