# """
# unified_exporter.py - Unified exporter for consistent metadata across all sources
# """

# import json
# from pathlib import Path
# from typing import Dict, Any, List, Optional, Iterable
# from datetime import datetime

# from ..chunkers.schema import CodeChunk


# class UnifiedExporter:
#     """
#     Unified exporter with consistent metadata schema for ALL sources:
#     - Git repositories (rich metadata)
#     - Local files (basic metadata)
#     - Single files
#     """
    
#     # Common metadata fields that should ALWAYS be present
#     REQUIRED_REPO_FIELDS = {
#         "repo_url": "",
#         "repo_name": "",
#         "extensions_included": "ALL",
#         "timestamp": "",
#         "basic": {},
#         "git": {},
#         "dependencies": {},
#         "structure": {},
#         "agentic_detection": {},
#     }
    
#     REQUIRED_FILE_FIELDS = {
#         "relative_path": "",
#         "size_bytes": 0,
#         "extension": "",
#         "is_binary": False,
#     }
    
#     def export(
#         self,
#         chunks: List[CodeChunk],
#         output_path: Path,
#         source_type: str = "git_repository",
#         source_metadata: Optional[Dict] = None,
#         print_stats: bool = True,
#     ) -> Dict[str, Any]:
#         """
#         Unified export method for all source types.
        
#         Args:
#             chunks: List of CodeChunk objects
#             output_path: Output file path
#             source_type: "git_repository", "local_files", or "single_file"
#             source_metadata: Source-specific metadata
#             print_stats: Print statistics to console
#         """
#         output_path.parent.mkdir(parents=True, exist_ok=True)
        
#         enhanced_chunks = []
#         for chunk in chunks:
#             chunk_dict = self._chunk_to_dict(chunk)
#             self._enhance_chunk_metadata(chunk_dict, source_type, source_metadata)
#             enhanced_chunks.append(chunk_dict)
        
#         # Write JSONL
#         with output_path.open("w", encoding="utf-8") as f:
#             for chunk_dict in enhanced_chunks:
#                 f.write(json.dumps(chunk_dict, ensure_ascii=False) + "\n")
        
#         # Generate statistics
#         stats = self._generate_stats(enhanced_chunks, source_type, source_metadata)
        
#         # Save stats file
#         stats_file = output_path.parent / f"{output_path.stem}_stats.json"
#         with open(stats_file, "w") as f:
#             json.dump(stats, f, indent=2)
        
#         if print_stats:
#             self._print_stats(stats, source_type)
        
#         return {
#             "chunks_file": str(output_path),
#             "stats_file": str(stats_file),
#             "total_chunks": len(chunks),
#             "source_type": source_type,
#             "timestamp": datetime.now().isoformat(),
#         }
    
#     def _chunk_to_dict(self, chunk: CodeChunk) -> Dict[str, Any]:
#         """Convert CodeChunk to dictionary with all fields"""
#         return {
#             "chunk_id": chunk.chunk_id,
#             "file_path": chunk.file_path,
#             "language": chunk.language,
#             "chunk_type": chunk.chunk_type,
#             "code": chunk.code,
#             "ast": {
#                 "symbol_type": chunk.ast.symbol_type,
#                 "name": chunk.ast.name,
#                 "parent": chunk.ast.parent,
#                 "docstring": chunk.ast.docstring,
#                 "decorators": chunk.ast.decorators,
#                 "imports": chunk.ast.imports,
#             } if chunk.ast else None,
#             "span": {
#                 "start_byte": chunk.span.start_byte,
#                 "end_byte": chunk.span.end_byte,
#                 "start_line": chunk.span.start_line,
#                 "end_line": chunk.span.end_line,
#                 "char_count": chunk.span.char_count,
#             } if chunk.span else None,
#             "metadata": self._sanitize_metadata(chunk.metadata),
#             "hierarchy": {
#                 "parent_id": chunk.hierarchy.parent_id,
#                 "children_ids": chunk.hierarchy.children_ids,
#                 "depth": chunk.hierarchy.depth,
#                 "is_primary": chunk.hierarchy.is_primary,
#                 "is_extracted": chunk.hierarchy.is_extracted,
#                 "lineage": getattr(chunk.hierarchy, "lineage", []),
#                 "sibling_index": getattr(chunk.hierarchy, "sibling_index", 0),
#             }
#         }
    
#     def _sanitize_metadata(self, metadata):
#         """Ensure metadata is JSON serializable"""
#         if not metadata:
#             return {}
        
#         if isinstance(metadata, dict):
#             return {k: self._sanitize_metadata(v) for k, v in metadata.items()}
#         elif isinstance(metadata, (list, tuple)):
#             return [self._sanitize_metadata(item) for item in metadata]
#         elif hasattr(metadata, '__dict__'):
#             return self._sanitize_metadata(metadata.__dict__)
#         else:
#             return metadata
    
#     def _enhance_chunk_metadata(
#         self,
#         chunk_dict: Dict,
#         source_type: str,
#         source_metadata: Optional[Dict]
#     ):
#         """Add consistent metadata based on source type"""
#         metadata = chunk_dict.get("metadata", {})
        
#         # Ensure repo_info exists
#         if "repo_info" not in metadata:
#             metadata["repo_info"] = {}
        
#         # Add source-specific metadata
#         if source_type == "git_repository":
#             self._add_git_repo_metadata(metadata, source_metadata)
#         elif source_type == "local_files":
#             self._add_local_files_metadata(metadata, source_metadata)
#         elif source_type == "single_file":
#             self._add_single_file_metadata(metadata, source_metadata)
        
#         # Always add processing info
#         metadata["processing_timestamp"] = datetime.now().isoformat()
#         metadata["source_type"] = source_type
        
#         # Ensure file_info is present
#         if "file_info" not in metadata:
#             # Try to extract from file_path
#             file_path = Path(chunk_dict["file_path"])
#             metadata["file_info"] = {
#                 "relative_path": chunk_dict["file_path"],
#                 "size_bytes": file_path.stat().st_size if file_path.exists() else 0,
#                 "extension": file_path.suffix.lower(),
#                 "is_binary": self._is_binary_file(file_path) if file_path.exists() else False,
#             }
        
#         chunk_dict["metadata"] = metadata
    
#     def _add_git_repo_metadata(self, metadata: Dict, repo_metadata: Optional[Dict]):
#         """Add Git repository metadata"""
#         if not repo_metadata:
#             return
        
#         # Ensure all required fields are present
#         repo_info = metadata["repo_info"]
        
#         # Copy ALL fields from repo_metadata
#         for key, value in repo_metadata.items():
#             repo_info[key] = value
        
#         # Add missing required fields
#         for field, default in self.REQUIRED_REPO_FIELDS.items():
#             if field not in repo_info:
#                 repo_info[field] = default
        
#         # Ensure git remote URL
#         if not repo_info.get("repo_url") and "git" in repo_info:
#             repo_info["repo_url"] = repo_info["git"].get("remote_url", "")
        
#         # Ensure timestamp
#         if not repo_info.get("timestamp"):
#             repo_info["timestamp"] = datetime.now().strftime("%Y%m%d_%H%M%S")
    
#     def _add_local_files_metadata(self, metadata: Dict, local_metadata: Optional[Dict]):
#         """Add local files metadata"""
#         repo_info = metadata["repo_info"]
#         repo_info["source_type"] = "local_files"
#         repo_info["timestamp"] = datetime.now().strftime("%Y%m%d_%H%M%S")
        
#         if local_metadata:
#             repo_info.update(local_metadata)
    
#     def _add_single_file_metadata(self, metadata: Dict, file_metadata: Optional[Dict]):
#         """Add single file metadata"""
#         repo_info = metadata["repo_info"]
#         repo_info["source_type"] = "single_file"
#         repo_info["timestamp"] = datetime.now().strftime("%Y%m%d_%H%M%S")
        
#         if file_metadata:
#             repo_info.update(file_metadata)
    
#     def _is_binary_file(self, file_path: Path, sample_size: int = 1024) -> bool:
#         """Check if file is binary"""
#         try:
#             with open(file_path, 'rb') as f:
#                 sample = f.read(sample_size)
            
#             if not sample:
#                 return False
            
#             # Check for null bytes
#             if b'\x00' in sample:
#                 return True
            
#             # Count printable ASCII
#             printable = sum(1 for byte in sample if 32 <= byte <= 126 or byte in (9, 10, 13))
#             return (printable / len(sample)) < 0.8
#         except:
#             return False
    
#     def _generate_stats(self, chunks: List[Dict], source_type: str, source_metadata: Optional[Dict]) -> Dict:
#         """Generate comprehensive statistics"""
#         stats = {
#             "export_summary": {
#                 "source_type": source_type,
#                 "total_chunks": len(chunks),
#                 "unique_files": len({c["file_path"] for c in chunks}),
#                 "export_timestamp": datetime.now().isoformat(),
#             },
#             "distributions": {
#                 "file_types": {},
#                 "chunk_types": {},
#                 "languages": {},
#             }
#         }
        
#         # Add source metadata
#         if source_metadata:
#             stats["source_metadata"] = source_metadata
        
#         # Calculate distributions
#         for chunk in chunks:
#             # File type
#             file_path = Path(chunk["file_path"])
#             file_type = file_path.suffix.lower()
#             stats["distributions"]["file_types"][file_type] = \
#                 stats["distributions"]["file_types"].get(file_type, 0) + 1
            
#             # Chunk type
#             chunk_type = chunk["chunk_type"]
#             stats["distributions"]["chunk_types"][chunk_type] = \
#                 stats["distributions"]["chunk_types"].get(chunk_type, 0) + 1
            
#             # Language
#             language = chunk["language"]
#             stats["distributions"]["languages"][language] = \
#                 stats["distributions"]["languages"].get(language, 0) + 1
        
#         return stats
    
#     def _print_stats(self, stats: Dict, source_type: str):
#         """Print formatted statistics"""
#         print("\n" + "="*70)
#         print(f"📊 EXPORT STATISTICS ({source_type.upper()})")
#         print("="*70)
        
#         summary = stats["export_summary"]
#         print(f"Source Type: {summary['source_type']}")
#         print(f"Total Chunks: {summary['total_chunks']:,}")
#         print(f"Unique Files: {summary['unique_files']:,}")
        
#         dist = stats["distributions"]
#         print(f"\n📁 File Types:")
#         for ftype, count in sorted(dist["file_types"].items(), 
#                                   key=lambda x: x[1], reverse=True)[:10]:
#             print(f"  {ftype or '(no ext)'}: {count:,}")
        
#         print(f"\n🧩 Chunk Types:")
#         for ctype, count in sorted(dist["chunk_types"].items(),
#                                   key=lambda x: x[1], reverse=True):
#             print(f"  {ctype}: {count:,}")
        
#         print("="*70)


# # Helper function for backward compatibility
# def export_unified(
#     chunks: List[CodeChunk],
#     output_path: Path,
#     source_type: str = "git_repository",
#     source_metadata: Optional[Dict] = None,
#     print_stats: bool = True,
# ) -> Dict[str, Any]:
#     """Helper function for unified export"""
#     exporter = UnifiedExporter()
#     return exporter.export(
#         chunks=chunks,
#         output_path=output_path,
#         source_type=source_type,
#         source_metadata=source_metadata,
#         print_stats=print_stats,
#     )