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

# Add parent directories to the Python path to find utils and parsers
source_path = Path(__file__).parent.parent
sys.path.append(str(source_path / 'utils'))
sys.path.append(str(source_path / 'parsers'))

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

def generate_guid_mappers(input_dir, output_dir, indent=None, shrink=False, ignored_folders=None):
    """
    Finds all .meta files and generates JSON files mapping GUIDs to asset paths.
    """
    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

    print("--> Finding all .meta files...")
    meta_files = find_files_by_extension(str(assets_dir), '.meta', ignored_folders=ignored_folders, project_root=input_dir)
    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'] = {}

    print("--> Parsing .meta files and mapping GUIDs to asset paths...")
    total_files = len(meta_files)
    for i, meta_file_path_str in enumerate(meta_files):
        if (i + 1) % 250 == 0:
            print(f"    ...processed {i+1}/{total_files} .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')
            # Use the full path from the project root for the guid_map value
            full_asset_path = input_dir / asset_file_path
            guid_maps[asset_type][guid] = full_asset_path.as_posix()
    print(f"    ...finished processing all {total_files} .meta files.")

    mappers_dir = output_dir / "GuidMappers"
    try:
        mappers_dir.mkdir(parents=True, exist_ok=True)
        print(f"--> Writing GUID mapper files to {mappers_dir}...")
        for asset_type, guid_map in guid_maps.items():
            if guid_map:
                output_path = mappers_dir / f"{asset_type}.json"
                # For the output JSON, we still want the project-relative path
                relative_guid_map = {g: Path(p).relative_to(input_dir).as_posix() for g, p in guid_map.items()}
                write_json(relative_guid_map, output_path, indent=indent, shrink=shrink)
                print(f"    -> Created {asset_type}.json with {len(guid_map)} entries.")
        print(f"--> Successfully created all GUID mappers.")
    except OSError as e:
        print(f"Error: Could not create GUID mapper directory or files. {e}", file=sys.stderr)
    
    # Return the map with full paths for the processor
    full_path_guid_map = {}
    for asset_type in guid_maps:
        full_path_guid_map.update(guid_maps[asset_type])
    return full_path_guid_map


def main():
    """
    Main function to run the mid-level data extraction process.
    This script generates a virtual file structure and detailed GUID mappers.
    """
    parser = argparse.ArgumentParser(
        description="Generates a virtual representation of the project's structure and GUID maps."
    )
    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."
    )
    args = parser.parse_args()

    # --- Load Configuration ---
    config = load_config()
    ignored_folders = config.get('ignored_folders', [])
    shrink_json = config.get('shrink_json', False)
    indent_level = config.get('indentation_level', 4)

    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

    print("\n--- Running Mid-Level Extraction ---")

    # --- Task 1: Replicate 'Assets' directory structure ---
    print("\n[1/3] Replicating 'Assets' directory structure...")
    replicate_directory_structure(str(assets_dir), str(output_assets_dir), ignored_folders=ignored_folders, project_root=input_dir)
    print("--> Directory structure replication complete.")

    # --- Task 2: Generate GUID Map and Mappers ---
    print("\n[2/3] Generating GUID Mappers...")
    guid_map = generate_guid_mappers(
        input_dir, 
        mid_level_output_dir, 
        indent=indent_level, 
        shrink=shrink_json, 
        ignored_folders=ignored_folders
    )
    print("--> GUID Mapper generation complete.")

    # --- Task 3: Orchestrate Scene and Prefab Parsing for Hierarchy ---
    print("\n[3/3] Parsing Scene and Prefab Hierarchies...")
    
    print("--> Finding scene and prefab files...")
    scene_files = find_files_by_extension(str(assets_dir), '.unity', ignored_folders=ignored_folders, project_root=input_dir)
    prefab_files = find_files_by_extension(str(assets_dir), '.prefab', ignored_folders=ignored_folders, project_root=input_dir)
    files_to_process = scene_files + prefab_files
    
    print(f"--> Found {len(files_to_process)} total scene/prefab files to process.")

    total_files = len(files_to_process)
    for i, file_path_str in enumerate(files_to_process):
        file_path = Path(file_path_str)
        
        relative_path = file_path.relative_to(assets_dir)
        output_json_path = (output_assets_dir / relative_path).with_suffix('.json')
        
        try:
            print(f"\n--- Processing {file_path.name} ({i+1}/{total_files}) ---")
            
            # Use the sophisticated processor for building the visual tree
            processor = UnitySceneProcessor(guid_map)
            
            print(f"    -> Loading and parsing file...")
            if not processor.load_documents(file_path):
                print(f"Warning: Could not load or parse {file_path.name}. Skipping.", file=sys.stderr)
                continue

            print(f"    -> Pass 1/6: Building relationship maps and creating basic nodes...")
            processor.process_first_pass()

            print(f"    -> Pass 2/6: Building hierarchy relationships...")
            processor.process_second_pass()

            print(f"    -> Pass 3/6: Verifying and fixing parent-child relationships...")
            processor.verification_pass()

            print(f"    -> Pass 4/6: Extracting components...")
            processor.process_third_pass()

            print(f"    -> Pass 5/6: Merging prefab data...")
            processor.merge_prefab_data_pass()
            
            print(f"    -> Pass 6/6: Assembling final hierarchy...")
            hierarchy = processor.get_hierarchy()
            
            output_json_path.parent.mkdir(parents=True, exist_ok=True)
            write_json(hierarchy, output_json_path, indent=indent_level, shrink=shrink_json)
            print(f"--> Successfully processed hierarchy for {file_path.name} -> {output_json_path}")

        except Exception as e:
            print(f"Error processing hierarchy for {file_path.name}: {e}", file=sys.stderr)

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

if __name__ == "__main__":
    main()
