import sqlite3
from typing import List, Dict
from pulse.core.brain_db import get_conn

def spreading_activation(start_nodes: List[str], decay: float = 0.6, threshold: float = 0.05, 
                         max_hops: int = 6, max_nodes: int = 50, edge_types: List[str] = None) -> List[Dict]:
    if edge_types is None:
        edge_types = ["RELATED_TO", "COACTIVATION"]
    """
    Phase 4A: Spreading Activation using SQLite Recursive CTE.
    Replaces 2-hop Python BFS with lightning-fast in-database graph traversal.
    
    Includes 1/sqrt(degree) dampening to prevent hub explosion.
    """
    if not start_nodes:
        return []
        
    conn = get_conn()
    
    # We pass the start nodes as a comma-separated string for the CTE base case
    placeholders = ",".join("?" * len(start_nodes))
    edge_placeholders = ",".join("?" * len(edge_types))
    
    query = f"""
    WITH RECURSIVE
      -- Base case: The starting nodes
      activation_wave(node_id, activation, hops, path) AS (
        SELECT
            id as node_id,
            1.0 as activation,
            0 as hops,
            id as path
        FROM graph_nodes
        WHERE id IN ({placeholders})

        UNION ALL

        -- Recursive step: Follow edges
        SELECT
            e.to_node,
            w.activation * e.confidence * ? * (1.0 / SQRT(MAX(1, (SELECT COUNT(*) FROM graph_edges ge WHERE ge.from_node = e.to_node OR ge.to_node = e.to_node)))),
            w.hops + 1,
            w.path || '->' || e.to_node
        FROM activation_wave w
        JOIN graph_edges e ON w.node_id = e.from_node
        WHERE w.hops < ?
          AND e.edge_type IN ({edge_placeholders})
          AND w.activation * e.confidence * ? * (1.0 / SQRT(MAX(1, (SELECT COUNT(*) FROM graph_edges ge WHERE ge.from_node = e.to_node OR ge.to_node = e.to_node)))) >= ?
          AND INSTR('->' || w.path || '->', '->' || e.to_node || '->') = 0 -- Prevent cycles securely
      )
    SELECT
        node_id as id,
        MAX(activation) as max_activation,
        MIN(hops) as min_hops
    FROM activation_wave
    GROUP BY node_id
    ORDER BY max_activation DESC
    LIMIT ?;
    """
    
    params = tuple(start_nodes) + (decay, max_hops) + tuple(edge_types) + (decay, threshold, max_nodes)
    
    with conn:
        cursor = conn.execute(query, params)
        results = [dict(row) for row in cursor.fetchall()]
        
    # We might want to enrich these with node text/metadata
    if results:
        node_ids = [r["id"] for r in results]
        placeholders2 = ",".join("?" * len(node_ids))
        with conn:
            cursor = conn.execute(f"SELECT id, text, type, confidence FROM graph_nodes WHERE id IN ({placeholders2})", tuple(node_ids))
            node_map = {row["id"]: dict(row) for row in cursor.fetchall()}
            
        for r in results:
            if r["id"] in node_map:
                r.update(node_map[r["id"]])
                
    return results
