#!/usr/bin/env python3
"""
Direct test runner for relationship_mapper tests (without pytest dependency)
"""

import sys
import os
import tempfile
from pathlib import Path
import json
import traceback

# Add parent directory to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

from core.knowledge.relationship_mapper import (
    RelationshipMapper,
    store_relationships,
    load_relationships
)


class TestRunner:
    """Simple test runner to replace pytest"""

    def __init__(self):
        self.passed = 0
        self.failed = 0
        self.errors = []

    def run_test(self, test_func, test_name):
        """Run a single test function"""
        try:
            test_func()
            self.passed += 1
            print(f"✓ {test_name}")
            return True
        except AssertionError as e:
            self.failed += 1
            self.errors.append((test_name, str(e)))
            print(f"✗ {test_name}: {e}")
            return False
        except Exception as e:
            self.failed += 1
            self.errors.append((test_name, traceback.format_exc()))
            print(f"✗ {test_name}: EXCEPTION: {e}")
            return False

    def print_summary(self):
        """Print test summary"""
        total = self.passed + self.failed
        print(f"\n{'='*60}")
        print(f"Test Results: {self.passed}/{total} passed")
        print(f"{'='*60}")

        if self.failed > 0:
            print(f"\nFailed Tests ({self.failed}):")
            for name, error in self.errors:
                print(f"\n  {name}:")
                print(f"    {error}")

        return self.failed == 0


# ============================================================================
# BLACK BOX TESTS
# ============================================================================

def test_basic_relationship_detection():
    """Test that basic relationships are detected from text"""
    mapper = RelationshipMapper(similarity_threshold=0.6)
    entities = ["Service A", "Service B"]
    text = "Service A uses Service B for processing."

    relationships = mapper.map_relationships(entities, text)

    assert len(relationships) > 0, "Should detect at least one relationship"
    assert any(r['source'] == "Service A" and r['target'] == "Service B"
              for r in relationships), "Should find Service A -> Service B relationship"


def test_multiple_relationship_types():
    """Test detection of different relationship types"""
    mapper = RelationshipMapper(similarity_threshold=0.6)
    entities = ["Module A", "Module B", "Module C"]
    text = """
    Module A depends on Module B.
    Module A uses Module C.
    """

    relationships = mapper.map_relationships(entities, text)

    relation_types = set(r['relation_type'] for r in relationships)
    assert 'depends_on' in relation_types, "Should detect depends_on relationship"
    assert 'uses' in relation_types, "Should detect uses relationship"


def test_store_and_load_relationships():
    """Test that relationships can be stored and loaded"""
    mapper = RelationshipMapper(similarity_threshold=0.6)

    with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.jsonl') as f:
        temp_file = f.name

    try:
        entities = ["Entity X", "Entity Y"]
        text = "Entity X references Entity Y in documentation."

        relationships = mapper.map_relationships(entities, text)
        count = store_relationships(relationships, temp_file)

        assert count > 0, "Should store at least one relationship"

        loaded = load_relationships(temp_file)
        assert len(loaded) == count, f"Should load same number of relationships (expected {count}, got {len(loaded)})"
        assert loaded[0]['source'] is not None, "Loaded relationship should have source"
        assert loaded[0]['target'] is not None, "Loaded relationship should have target"

    finally:
        if os.path.exists(temp_file):
            os.remove(temp_file)


def test_filtering_by_confidence():
    """Test loading relationships with confidence filter"""
    with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.jsonl') as f:
        temp_file = f.name

    try:
        test_relationships = [
            {
                "source": "A", "target": "B", "relation_type": "uses",
                "confidence": 0.9, "detection_method": "test", "timestamp": "2026-01-25",
                "metadata": {}
            },
            {
                "source": "C", "target": "D", "relation_type": "uses",
                "confidence": 0.5, "detection_method": "test", "timestamp": "2026-01-25",
                "metadata": {}
            }
        ]

        store_relationships(test_relationships, temp_file)
        loaded = load_relationships(temp_file, min_confidence=0.8)

        assert len(loaded) == 1, f"Should only load high confidence relationships (got {len(loaded)})"
        assert loaded[0]['confidence'] >= 0.8, "Loaded relationship should meet threshold"

    finally:
        if os.path.exists(temp_file):
            os.remove(temp_file)


# ============================================================================
# WHITE BOX TESTS
# ============================================================================

def test_detect_code_imports_python():
    """Test Python import detection"""
    mapper = RelationshipMapper(similarity_threshold=0.6)
    entities = ["Database", "UserService", "Authentication"]
    text = """
import Database
from UserService import get_user
from Authentication import verify
    """

    relationships = mapper._detect_code_imports(text, entities)

    assert len(relationships) > 0, "Should detect import relationships"
    assert any(r['relation_type'] == 'depends_on' for r in relationships), \
        "Should create depends_on relationships"
    assert any(r['detection_method'] == 'code_import' for r in relationships), \
        "Should mark as code_import"


def test_detect_contains_relationships():
    """Test file structure containment detection"""
    mapper = RelationshipMapper(similarity_threshold=0.6)

    with tempfile.TemporaryDirectory() as tmpdir:
        service_dir = Path(tmpdir) / "UserService"
        service_dir.mkdir()
        test_file = service_dir / "handler.py"
        test_file.touch()

        entities = ["UserService", "handler"]
        relationships = mapper._detect_contains_relationships(
            str(test_file), entities
        )

        assert len(relationships) > 0, "Should detect containment relationship"
        assert any(r['relation_type'] == 'contains' for r in relationships), \
            "Should create contains relationships"


def test_detect_references_markdown_links():
    """Test documentation reference detection via markdown links"""
    mapper = RelationshipMapper(similarity_threshold=0.6)
    entities = ["API Documentation", "UserGuide"]
    text = """
    See the [API Documentation](./api.md) for details.
    Refer to [UserGuide](#user-guide) for instructions.
    """

    relationships = mapper._detect_references(text, entities)

    assert len(relationships) > 0, "Should detect reference relationships"
    assert any(r['relation_type'] == 'references' for r in relationships), \
        "Should create references relationships"
    assert any('link_url' in r['metadata'] for r in relationships), \
        "Should include link metadata"


def test_detect_similarity():
    """Test similarity detection"""
    mapper = RelationshipMapper(similarity_threshold=0.6)
    entities = ["UserService", "UserServiceImpl", "DataService"]

    relationships = mapper._detect_similarity(entities, None)

    similar_pairs = [(r['source'], r['target']) for r in relationships
                    if r['relation_type'] == 'similar_to']

    assert len(similar_pairs) > 0, "Should detect similar entities"


def test_calculate_similarity():
    """Test similarity calculation"""
    mapper = RelationshipMapper(similarity_threshold=0.6)

    similarity_identical = mapper._calculate_similarity("test", "test")
    assert similarity_identical == 1.0, "Identical strings should have similarity of 1.0"

    similarity_different = mapper._calculate_similarity("apple", "orange")
    assert similarity_different < 0.5, "Different strings should have low similarity"


# ============================================================================
# INTEGRATION TESTS
# ============================================================================

def test_full_pipeline():
    """Test complete pipeline: detect -> store -> load -> filter"""
    mapper = RelationshipMapper(similarity_threshold=0.6)

    entities = ["ServiceA", "ServiceB", "ServiceC"]
    text = """
    ServiceA uses ServiceB for authentication.
    ServiceB depends on ServiceC.
    See [ServiceA Documentation](./docs/servicea.md) for details.

    import ServiceB
    from ServiceC import authenticate
    """

    with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.jsonl') as f:
        temp_file = f.name

    try:
        # Detect relationships
        relationships = mapper.map_relationships(entities, text)
        assert len(relationships) > 0, "Should detect relationships"

        # Store relationships
        count = store_relationships(relationships, temp_file)
        assert count == len(relationships), "Should store all relationships"

        # Load all relationships
        loaded = load_relationships(temp_file)
        assert len(loaded) == count, "Should load all relationships"

        # Load with filters
        high_conf = load_relationships(temp_file, min_confidence=0.8)
        assert len(high_conf) <= count, "Filtered results should be <= total"

    finally:
        if os.path.exists(temp_file):
            os.remove(temp_file)


def test_edge_case_no_entities():
    """Test handling of empty entity list"""
    mapper = RelationshipMapper(similarity_threshold=0.6)
    entities = []
    text = "Some text without entities."

    relationships = mapper.map_relationships(entities, text)

    assert len(relationships) == 0, "Should return empty list for no entities"


# ============================================================================
# MAIN TEST RUNNER
# ============================================================================

def main():
    """Run all tests"""
    runner = TestRunner()

    print("="*60)
    print("Running Relationship Mapper Tests")
    print("="*60)

    # Black box tests
    print("\n[BLACK BOX TESTS]")
    runner.run_test(test_basic_relationship_detection, "test_basic_relationship_detection")
    runner.run_test(test_multiple_relationship_types, "test_multiple_relationship_types")
    runner.run_test(test_store_and_load_relationships, "test_store_and_load_relationships")
    runner.run_test(test_filtering_by_confidence, "test_filtering_by_confidence")

    # White box tests
    print("\n[WHITE BOX TESTS]")
    runner.run_test(test_detect_code_imports_python, "test_detect_code_imports_python")
    runner.run_test(test_detect_contains_relationships, "test_detect_contains_relationships")
    runner.run_test(test_detect_references_markdown_links, "test_detect_references_markdown_links")
    runner.run_test(test_detect_similarity, "test_detect_similarity")
    runner.run_test(test_calculate_similarity, "test_calculate_similarity")

    # Integration tests
    print("\n[INTEGRATION TESTS]")
    runner.run_test(test_full_pipeline, "test_full_pipeline")
    runner.run_test(test_edge_case_no_entities, "test_edge_case_no_entities")

    # Print summary
    success = runner.print_summary()

    return 0 if success else 1


if __name__ == '__main__':
    sys.exit(main())
