import argparse
import sys
import json
import shutil
from pathlib import Path

# Add the utils directory to the Python path
utils_path = Path(__file__).parent / 'utils'
sys.path.append(str(utils_path))

from file_utils import replicate_directory_structure, find_files_by_extension, create_guid_to_path_map
from json_utils import write_json
from scene_processor import UnitySceneProcessor

def generate_guid_mappers(input_dir, output_dir, indent=None):
    """
    Finds all .meta files and generates JSON files mapping GUIDs to asset paths.
    """
    print("\n--- Starting GUID Mapper Generation ---")
    assets_dir = input_dir / "Assets"
    if not assets_dir.is_dir():
        print(f"Error: 'Assets' directory not found in '{input_dir}'", file=sys.stderr)
        return

    meta_files = find_files_by_extension(str(assets_dir), '.meta')
    print(f"Found {len(meta_files)} .meta files to process.")

    asset_type_map = {
        '.prefab': 'prefabs', '.unity': 'scenes', '.mat': 'materials',
        '.cs': 'scripts', '.png': 'textures', '.jpg': 'textures',
        '.jpeg': 'textures', '.asset': 'scriptable_objects',
    }
    
    guid_maps = {value: {} for value in asset_type_map.values()}
    guid_maps['others'] = {}

    for meta_file_path_str in meta_files:
        meta_file_path = Path(meta_file_path_str)
        asset_file_path = Path(meta_file_path_str.rsplit('.meta', 1)[0])

        if not asset_file_path.is_file():
            continue

        guid = None
        try:
            with open(meta_file_path, 'r', encoding='utf-8') as f:
                for line in f:
                    if line.strip().startswith('guid:'):
                        guid = line.strip().split(':')[1].strip()
                        break
        except Exception as e:
            print(f"Warning: Could not read or parse guid from {meta_file_path}. {e}", file=sys.stderr)
            continue

        if guid:
            asset_ext = asset_file_path.suffix.lower()
            asset_type = asset_type_map.get(asset_ext, 'others')
            relative_path = asset_file_path.relative_to(input_dir).as_posix()
            guid_maps[asset_type][guid] = relative_path

    mappers_dir = output_dir / "GuidMappers"
    try:
        mappers_dir.mkdir(parents=True, exist_ok=True)
        for asset_type, guid_map in guid_maps.items():
            if guid_map:
                output_path = mappers_dir / f"{asset_type}.json"
                write_json(guid_map, output_path, indent=indent)
        print(f"Successfully created GUID mappers in {mappers_dir}")
    except OSError as e:
        print(f"Error: Could not create GUID mapper directory or files. {e}", file=sys.stderr)

def main():
    """
    Main function to run the mid-level data extraction process.
    This script orchestrates the parsing of scene and prefab files.
    """
    parser = argparse.ArgumentParser(
        description="Generates a virtual representation of the project's structure."
    )
    parser.add_argument(
        "--input",
        type=str,
        required=True,
        help="The root directory of the target Unity project."
    )
    parser.add_argument(
        "--output",
        type=str,
        required=True,
        help="The directory where the generated output folder will be saved."
    )
    parser.add_argument(
        "--indent",
        type=int,
        default=None,
        help="Indentation level for JSON output. Defaults to None (compact)."
    )
    args = parser.parse_args()

    input_dir = Path(args.input).resolve()
    output_dir = Path(args.output).resolve()

    if not input_dir.is_dir():
        print(f"Error: Input path '{input_dir}' is not a valid directory.", file=sys.stderr)
        sys.exit(1)

    # --- Setup Output Directories ---
    mid_level_output_dir = output_dir / "MidLevel"
    output_assets_dir = mid_level_output_dir / "Assets"
    try:
        output_assets_dir.mkdir(parents=True, exist_ok=True)
        print(f"Output will be saved to: {mid_level_output_dir}")
    except OSError as e:
        print(f"Error: Could not create output directory '{mid_level_output_dir}'. {e}", file=sys.stderr)
        sys.exit(1)

    assets_dir = input_dir / "Assets"
    if not assets_dir.is_dir():
        print(f"Warning: 'Assets' directory not found in '{input_dir}'. Skipping all processing.", file=sys.stderr)
        return

    # --- Task 1: Replicate 'Assets' directory structure ---
    print(f"\n--- Replicating 'Assets' directory structure ---")
    replicate_directory_structure(str(assets_dir), str(output_assets_dir))
    print("Directory structure replication complete.")

    # --- Task 2: Generate GUID Map ---
    print("\n--- Generating GUID Map ---")
    guid_map = create_guid_to_path_map(str(input_dir))
    guid_map_path = mid_level_output_dir / "guid_map.json"
    try:
        # Use the new centralized utility
        write_json(guid_map, guid_map_path, indent=args.indent)
        print(f"Successfully created GUID map: {guid_map_path}")
    except Exception as e:
        print(f"Error writing GUID map: {e}", file=sys.stderr)
        sys.exit(1)

    # --- Task 3: Generate Detailed GUID Mappers ---
    generate_guid_mappers(input_dir, mid_level_output_dir, indent=args.indent)

    # --- Task 4: Orchestrate Scene and Prefab Parsing ---
    print("\n--- Starting Scene/Prefab Parsing Orchestration ---")
    
    scene_files = find_files_by_extension(str(assets_dir), '.unity')
    prefab_files = find_files_by_extension(str(assets_dir), '.prefab')
    files_to_process = scene_files + prefab_files
    
    print(f"Found {len(files_to_process)} scene/prefab files to process.")

    # Create a single processor instance to use for all files
    processor = UnitySceneProcessor(guid_map)

    for file_path_str in files_to_process:
        file_path = Path(file_path_str)
        
        relative_path = file_path.relative_to(assets_dir)
        output_path = output_assets_dir / relative_path
        output_path = output_path.with_suffix('.json')
        
        try:
            print(f"\n--- Processing: {file_path.name} ---")
            # Process the file and get the result
            result = processor.process_file(file_path)
            
            # Ensure the output directory exists
            output_path.parent.mkdir(parents=True, exist_ok=True)

            # Write the result using the centralized utility
            write_json(result, output_path, indent=args.indent)
            print(f"Successfully processed {file_path.name} -> {output_path}")

        except Exception as e:
            print(f"Error processing {file_path.name}: {e}", file=sys.stderr)
            # Potentially continue to the next file
            # sys.exit(1)

    print("\nMid-level extraction complete.")

if __name__ == "__main__":
    main()
