import os
import shutil
import tempfile
import traceback
import logging
from typing import Any, Dict, List, Optional

# Configure logging
logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s')
logger = logging.getLogger("verify_backends")

try:
    from semantica.graph_store.graph_store import GraphStore
except ImportError:
    logger.error("Failed to import semantica. Make sure you are in the project root or semantica is installed.")
    exit(1)

def verify_backend(backend_name: str, config: Dict[str, Any]) -> bool:
    logger.info(f"\n{'='*20} Verifying {backend_name.upper()} {'='*20}")
    store = None
    try:
        # Initialize
        logger.info(f"Initializing GraphStore with backend='{backend_name}'...")
        store = GraphStore(backend=backend_name, **config)
        
        # Connect
        logger.info(f"Connecting to {backend_name}...")
        try:
            store.connect()
            logger.info("Connection successful.")
        except Exception as e:
            logger.error(f"Connection failed: {e}")
            logger.info(f"Skipping operations for {backend_name} due to connection failure.")
            return False

        # Create Node
        logger.info("Creating test node...")
        node_props = {"name": "TestNode", "test_id": "123"}
        node = store.create_node(labels=["TestLabel"], properties=node_props)
        logger.info(f"Node created: {node}")
        
        node_id = node.get("id")
        if not node_id:
            raise Exception("Node created but returned no ID")

        # Get Node
        logger.info(f"Retrieving node {node_id}...")
        fetched_node = store.get_node(node_id)
        if not fetched_node:
            raise Exception("Failed to retrieve created node")
        if fetched_node.get("properties", {}).get("name") != "TestNode":
            raise Exception("Retrieved node properties do not match")
        logger.info("Node retrieved successfully.")

        # Update Node
        logger.info("Updating node...")
        store.update_node(node_id, properties={"updated": True})
        updated_node = store.get_node(node_id)
        if not updated_node.get("properties", {}).get("updated"):
             raise Exception("Update failed")
        logger.info("Node updated successfully.")

        # Create Relationship
        # We need a second node
        node2 = store.create_node(labels=["TestLabel"], properties={"name": "TestNode2"})
        logger.info("Creating relationship...")
        rel = store.create_relationship(node_id, node2["id"], "TEST_REL", {"since": 2024})
        logger.info(f"Relationship created: {rel}")
        rel_id = rel.get("id")

        # Get Relationship
        # Note: Implementation details of get_relationships vary, assume standard interface
        logger.info("Retrieving relationship...")
        rels = store.get_relationships(node_id=node_id, direction="out")
        found = False
        for r in rels:
            if r.get("id") == rel_id:
                found = True
                break
        if not found:
            logger.warning("Relationship not found in list (could be eventual consistency or implementation nuance)")
        else:
            logger.info("Relationship retrieved successfully.")

        # Delete Relationship
        if rel_id:
            logger.info("Deleting relationship...")
            store.delete_relationship(rel_id)
            logger.info("Relationship deleted.")

        # Delete Nodes
        logger.info("Deleting nodes...")
        store.delete_node(node_id)
        store.delete_node(node2["id"])
        
        check = store.get_node(node_id)
        if check:
            logger.warning("Node still exists after deletion (could be eventual consistency)")
        else:
            logger.info("Node deletion verified.")

        logger.info(f"SUCCESS: {backend_name} passed all verification steps.")
        return True

    except Exception as e:
        logger.error(f"FAILURE: {backend_name} encountered an error: {str(e)}")
        # traceback.print_exc()
        return False
    finally:
        if store:
            try:
                store.close()
            except:
                pass

def main():
    results = {}
    
    # 2. Neo4j (Requires Server)
    # Using defaults or env vars. If not running, this will fail connection, which is expected.
    # To test properly, user needs to set GRAPH_STORE_NEO4J_URI etc.
    results['neo4j'] = verify_backend('neo4j', {})

    # 3. FalkorDB (Requires Redis)
    results['falkordb'] = verify_backend('falkordb', {})

    print("\n" + "="*50)
    print("VERIFICATION SUMMARY")
    print("="*50)
    for backend, result in results.items():
        status = "PASSED" if result else "FAILED (or Skipped)"
        print(f"{backend.ljust(15)}: {status}")
    print("="*50)

if __name__ == "__main__":
    main()
