#!/usr/bin/env python3
"""
Script to rename files in custom/test_cases/ with numeric prefixes based on
the order they appear in test_cases.json, and update compare_to references inside files.
"""

import json
import re
from pathlib import Path

def clean_id(test_id):
    """Remove old prefixes (ZZZZ_, ZZZ_, ZZ_, Z_) from the test_id"""
    test_id = test_id[3:]
    for prefix in ['ZZZZ_', 'ZZZ_', 'ZZ_', 'Z_']:
        if test_id.startswith(prefix):
            return test_id[len(prefix):]
    return test_id

def update_compare_to_in_file(file_path, id_mapping):
    """Update compare_to references in a JSON file"""
    with open(file_path, 'r', encoding='utf-8') as f:
        content = f.read()
    
    original_content = content
    changes_made = []
    
    # Find all compare_to values
    for old_id, new_id in id_mapping.items():
        # Pattern to match "compare_to": "old_id"
        pattern = f'"compare_to":\\s*"{re.escape(old_id)}"'
        replacement = f'"compare_to": "{new_id}"'
        
        if re.search(pattern, content):
            content = re.sub(pattern, replacement, content)
            changes_made.append(f"{old_id} -> {new_id}")
    
    # Write back if changes were made
    if content != original_content:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(content)
        return changes_made
    return []

def main():
    # Read the test_cases.json file
    test_cases_file = Path(__file__).parent / "test_cases.json"
    custom_test_cases_dir = Path(__file__).parent / "custom" / "test_cases"
    
    print(f"Reading test cases from: {test_cases_file}")
    with open(test_cases_file, 'r', encoding='utf-8') as f:
        test_cases = json.load(f)
    
    # Extract test case IDs (the main level IDs, not individual IDs)
    test_case_ids = []
    for test_case in test_cases:
        if 'id' in test_case:
            test_case_ids.append(test_case['id'])
    
    print(f"Found {len(test_case_ids)} test cases in test_cases.json")
    
    # Get all files in custom/test_cases directory
    if not custom_test_cases_dir.exists():
        print(f"Error: Directory {custom_test_cases_dir} does not exist")
        return
    
    existing_files = {f.stem: f for f in custom_test_cases_dir.glob("*.json")}
    print(f"Found {len(existing_files)} JSON files in {custom_test_cases_dir}")
    
    # Calculate the number of digits needed for padding
    num_digits = len(str(len(test_case_ids)))
    
    # Create mappings: old_id -> new_id (with prefix)
    id_mapping = {}  # Maps original IDs to new prefixed IDs
    renames = []
    matched_files = set()
    
    for index, test_id in enumerate(test_case_ids, start=0):
        # Check if a file with this ID exists (with or without numeric prefix)
        file_found = None
        
        # First, try exact match
        if test_id in existing_files:
            file_found = existing_files[test_id]
        else:
            # Try to find file that ends with this ID (removing any existing prefix)
            for stem, file_path in existing_files.items():
                # Remove any existing numeric prefix pattern (e.g., "01_", "ZZ_", etc.)
                # Check if the stem matches or if test_id matches after removing prefix
                if stem == test_id or test_id in stem:
                    file_found = file_path
                    break
        
        if file_found and file_found.stem not in matched_files:
            # Remove old prefixes from the test_id
            cleaned_id = clean_id(test_id)
            
            # Create new filename with padded number prefix
            new_id = f"{str(index).zfill(num_digits+1)}_{cleaned_id}"
            new_name = f"{new_id}.json"
            new_path = custom_test_cases_dir / new_name
            
            # Store mapping for updating compare_to references
            # Map from original ID (without any prefix) to new prefixed ID
            id_mapping[test_id] = new_id
            id_mapping[cleaned_id] = new_id
            
            if file_found.name != new_name:
                renames.append((file_found, new_path, test_id, new_id))
                matched_files.add(file_found.stem)
    
    print(f"\nFound {len(renames)} files to rename:")
    print("-" * 80)
    
    if not renames:
        print("No files need to be renamed.")
        return
    
    # Show the planned renames
    for old_path, new_path, test_id, new_id in renames:
        print(f"{old_path.name:60s} -> {new_path.name}")
    
    # Ask for confirmation
    print("-" * 80)
    response = input(f"\nRename {len(renames)} files and update compare_to references? (yes/no): ").strip().lower()
    
    if response == 'yes':
        print("\nStep 1: Updating compare_to references in files...")
        all_json_files = list(custom_test_cases_dir.glob("*.json"))
        files_updated = 0
        for json_file in all_json_files:
            changes = update_compare_to_in_file(json_file, id_mapping)
            if changes:
                files_updated += 1
                print(f"  Updated {json_file.name}: {len(changes)} reference(s)")
        
        print(f"\nUpdated compare_to references in {files_updated} file(s)")
        
        print("\nStep 2: Renaming files...")
        # Use a two-pass approach to avoid conflicts
        # First pass: rename to temporary names
        temp_renames = []
        for old_path, new_path, test_id, new_id in renames:
            temp_path = custom_test_cases_dir / f"_temp_{old_path.name}"
            old_path.rename(temp_path)
            temp_renames.append((temp_path, new_path))
        
        # Second pass: rename to final names
        for temp_path, new_path in temp_renames:
            temp_path.rename(new_path)
        
        print(f"\nSuccessfully renamed {len(renames)} files!")
    else:
        print("\nOperation cancelled.")
    
    # Report unmatched files
    unmatched_files = []
    for stem, file_path in existing_files.items():
        if stem not in matched_files:
            unmatched_files.append(file_path.name)
    
    if unmatched_files:
        print(f"\n{len(unmatched_files)} files in custom/test_cases/ were not matched to test_cases.json:")
        for filename in sorted(unmatched_files):
            print(f"  - {filename}")

if __name__ == "__main__":
    main()
