"""
Integration Tests for Provenance Module

Tests end-to-end integration of provenance tracking across all modules.
"""

import pytest
from semantica.provenance import ProvenanceManager
from semantica.kg import ProvenanceTracker as KGTracker
from semantica.split import ProvenanceTracker as SplitTracker
from semantica.split.semantic_chunker import Chunk


class TestEndToEndProvenance:
    """Test end-to-end provenance tracking."""
    
    def test_unified_manager_basic_flow(self):
        """Test basic flow with unified manager."""
        prov_mgr = ProvenanceManager()
        
        # Track entity
        prov_mgr.track_entity("entity_1", source="doc_1")
        
        # Track chunk
        prov_mgr.track_chunk("chunk_1", source_document="doc_1")
        
        # Verify both tracked
        entity_prov = prov_mgr.get_provenance("entity_1")
        chunk_prov = prov_mgr.get_provenance("chunk_1")
        
        assert entity_prov is not None
        assert chunk_prov is not None
    
    def test_kg_to_unified_integration(self):
        """Test kg.ProvenanceTracker uses unified backend."""
        kg_tracker = KGTracker()
        
        # Track with kg tracker
        kg_tracker.track_entity("kg_entity_1", source="kg_doc_1")
        
        # Verify it was tracked
        lineage = kg_tracker.get_lineage("kg_entity_1")
        
        assert lineage is not None
        assert "sources" in lineage
    
    def test_split_to_unified_integration(self):
        """Test split.ProvenanceTracker uses unified backend."""
        split_tracker = SplitTracker()
        
        chunk = Chunk(
            text="Test chunk",
            start_index=0,
            end_index=10,
            metadata={}
        )
        chunk.id = "split_chunk_1"
        
        # Track with split tracker
        split_tracker.track_chunk(chunk, source_document="split_doc_1")
        
        # Verify it was tracked
        prov = split_tracker.get_provenance("split_chunk_1")
        
        assert prov is not None
        assert prov.chunk_id == "split_chunk_1"
    
    def test_cross_module_lineage(self):
        """Test lineage tracing across modules."""
        prov_mgr = ProvenanceManager()
        
        # Track document
        prov_mgr.track_entity(
            entity_id="doc_1",
            source="original_source.pdf",
            entity_type="document"
        )
        
        # Track chunk from document
        prov_mgr.track_chunk(
            chunk_id="chunk_1",
            source_document="doc_1",
            parent_chunk_id="doc_1"
        )
        
        # Track entity from chunk
        prov_mgr.track_entity(
            entity_id="entity_1",
            source="chunk_1",
            entity_type="entity"
        )
        
        # Trace lineage
        lineage = prov_mgr.get_lineage("entity_1")
        
        assert lineage is not None
        assert len(lineage.get("source_documents", [])) > 0


class TestPerformance:
    """Test performance of provenance tracking."""
    
    def test_bulk_entity_tracking(self):
        """Test tracking many entities."""
        prov_mgr = ProvenanceManager()
        
        # Track 1000 entities
        entities = [{"id": f"entity_{i}"} for i in range(1000)]
        count = prov_mgr.track_entities_batch(entities, source="bulk_doc")
        
        assert count == 1000
    
    def test_bulk_chunk_tracking(self):
        """Test tracking many chunks."""
        prov_mgr = ProvenanceManager()
        
        # Track 1000 chunks
        chunks = [
            {"id": f"chunk_{i}", "start_index": i*100, "end_index": (i+1)*100}
            for i in range(1000)
        ]
        count = prov_mgr.track_chunks_batch(chunks, source_document="bulk_doc")
        
        assert count == 1000
    
    def test_lineage_tracing_performance(self):
        """Test lineage tracing with deep chains."""
        prov_mgr = ProvenanceManager()
        
        # Create chain of 100 entities
        for i in range(100):
            parent_id = f"entity_{i-1}" if i > 0 else None
            prov_mgr.track_entity(
                entity_id=f"entity_{i}",
                source=f"doc_{i}",
                metadata={"parent": parent_id}
            )
        
        # Trace lineage (should be fast)
        lineage = prov_mgr.get_lineage("entity_99")
        
        assert lineage is not None


class TestDataIntegrity:
    """Test data integrity and checksums."""
    
    def test_checksum_generation(self):
        """Test that checksums are generated."""
        prov_mgr = ProvenanceManager()
        
        entry = prov_mgr.track_entity(
            entity_id="integrity_test",
            source="test_doc"
        )
        
        assert entry.checksum is not None
        assert len(entry.checksum) == 64  # SHA-256 hex length
    
    def test_checksum_verification(self):
        """Test checksum verification."""
        from semantica.provenance import compute_checksum, verify_checksum
        
        prov_mgr = ProvenanceManager()
        
        entry = prov_mgr.track_entity(
            entity_id="verify_test",
            source="test_doc"
        )
        
        # Verify checksum
        is_valid = verify_checksum(entry)
        assert is_valid is True


class TestStorageBackends:
    """Test different storage backends."""
    
    def test_in_memory_storage(self):
        """Test in-memory storage backend."""
        from semantica.provenance import InMemoryStorage
        
        storage = InMemoryStorage()
        prov_mgr = ProvenanceManager(storage=storage)
        
        prov_mgr.track_entity("mem_entity_1", source="mem_doc_1")
        
        prov = prov_mgr.get_provenance("mem_entity_1")
        assert prov is not None
    
    def test_sqlite_storage(self):
        """Test SQLite storage backend."""
        import tempfile
        import os
        from semantica.provenance import SQLiteStorage
        
        with tempfile.NamedTemporaryFile(delete=False, suffix=".db") as tmp:
            db_path = tmp.name
        
        try:
            storage = SQLiteStorage(db_path)
            prov_mgr = ProvenanceManager(storage=storage)
            
            prov_mgr.track_entity("sql_entity_1", source="sql_doc_1")
            
            # Verify persistence
            prov_mgr2 = ProvenanceManager(storage_path=db_path)
            prov = prov_mgr2.get_provenance("sql_entity_1")
            
            assert prov is not None
        finally:
            if os.path.exists(db_path):
                os.unlink(db_path)


class TestErrorHandling:
    """Test error handling and graceful degradation."""
    
    def test_missing_entity_returns_none(self):
        """Test that missing entity returns None."""
        prov_mgr = ProvenanceManager()
        
        prov = prov_mgr.get_provenance("nonexistent")
        
        assert prov is None
    
    def test_empty_lineage_returns_empty_dict(self):
        """Test that empty lineage returns empty dict."""
        prov_mgr = ProvenanceManager()
        
        lineage = prov_mgr.get_lineage("nonexistent")
        
        assert lineage == {}
    
    def test_graceful_failure_on_invalid_data(self):
        """Test graceful handling of invalid data."""
        prov_mgr = ProvenanceManager()
        
        # Should not raise exception
        try:
            prov_mgr.track_entity("", source="")
            success = True
        except Exception:
            success = False
        
        assert success is True


class TestStatistics:
    """Test provenance statistics."""
    
    def test_get_statistics(self):
        """Test getting provenance statistics."""
        prov_mgr = ProvenanceManager()
        
        # Track various entities
        prov_mgr.track_entity("entity_1", source="doc_1")
        prov_mgr.track_entity("entity_2", source="doc_1")
        prov_mgr.track_chunk("chunk_1", source_document="doc_1")
        
        stats = prov_mgr.get_statistics()
        
        assert "total_entries" in stats
        assert "entity_types" in stats
        assert stats["total_entries"] >= 3
    
    def test_clear_provenance(self):
        """Test clearing provenance data."""
        prov_mgr = ProvenanceManager()
        
        prov_mgr.track_entity("entity_1", source="doc_1")
        prov_mgr.track_entity("entity_2", source="doc_1")
        
        count = prov_mgr.clear()
        
        assert count >= 2
        
        # Verify cleared
        prov = prov_mgr.get_provenance("entity_1")
        assert prov is None
