"""
Graph construction and export functionality for Woseco concept networks.
"""
import networkx as nx
from typing import List, Optional
import os


def build_graph(concepts: List[str], graph_type: str = "chain") -> nx.Graph:
    """
    Build a NetworkX graph from a list of concepts.

    Args:
        concepts: List of concepts in order
        graph_type: Type of graph to build:
            - "chain": Connect consecutive concepts (recommended)
            - "dense": Connect all concepts in the list

    Returns:
        NetworkX Graph object
    """
    G = nx.Graph()

    if not concepts:
        return G

    # Add all concepts as nodes
    for concept in concepts:
        if concept:  # Skip empty strings
            G.add_node(concept)

    if graph_type == "chain":
        # Connect consecutive concepts (original method)
        for i in range(len(concepts) - 1):
            if concepts[i] and concepts[i + 1]:
                G.add_edge(concepts[i], concepts[i + 1])

    elif graph_type == "dense":
        # Connect all concepts to each other (alternative method)
        for i in range(len(concepts)):
            for j in range(i + 1, len(concepts)):
                if concepts[i] and concepts[j]:
                    G.add_edge(concepts[i], concepts[j])

    return G


def build_graphs_from_list(
    concept_lists: List[List[str]],
    graph_type: str = "chain"
) -> List[nx.Graph]:
    """
    Build multiple graphs from a list of concept lists.

    Args:
        concept_lists: List of concept lists (e.g., one per story)
        graph_type: Type of graph to build

    Returns:
        List of NetworkX Graph objects
    """
    return [build_graph(concepts, graph_type) for concepts in concept_lists]


def export_graph(
    graph: nx.Graph,
    output_path: str,
    format: str = "graphml"
) -> None:
    """
    Export a graph to a file.

    Args:
        graph: NetworkX graph
        output_path: Path to save the graph
        format: Export format ('graphml', 'gexf', 'gml', 'edgelist')
    """
    # Create directory if it doesn't exist
    os.makedirs(os.path.dirname(output_path), exist_ok=True)

    if format == "graphml":
        nx.write_graphml(graph, output_path)
    elif format == "gexf":
        nx.write_gexf(graph, output_path)
    elif format == "gml":
        nx.write_gml(graph, output_path)
    elif format == "edgelist":
        nx.write_edgelist(graph, output_path)
    else:
        raise ValueError(f"Unsupported format: {format}")


def export_graphs(
    graphs: List[nx.Graph],
    output_dir: str,
    prefix: str = "graph",
    format: str = "graphml"
) -> None:
    """
    Export multiple graphs to files.

    Args:
        graphs: List of NetworkX graphs
        output_dir: Directory to save graphs
        prefix: Prefix for filenames
        format: Export format
    """
    os.makedirs(output_dir, exist_ok=True)

    for i, graph in enumerate(graphs):
        filename = f"{prefix}_{i}.{format}"
        filepath = os.path.join(output_dir, filename)
        export_graph(graph, filepath, format)

    print(f"Exported {len(graphs)} graphs to {output_dir}")


def load_graph(input_path: str, format: str = "graphml") -> nx.Graph:
    """
    Load a graph from a file.

    Args:
        input_path: Path to graph file
        format: Graph format

    Returns:
        NetworkX Graph object
    """
    if format == "graphml":
        return nx.read_graphml(input_path)
    elif format == "gexf":
        return nx.read_gexf(input_path)
    elif format == "gml":
        return nx.read_gml(input_path)
    elif format == "edgelist":
        return nx.read_edgelist(input_path)
    else:
        raise ValueError(f"Unsupported format: {format}")


def merge_graphs(graphs: List[nx.Graph]) -> nx.Graph:
    """
    Merge multiple graphs into a single graph.

    Args:
        graphs: List of graphs to merge

    Returns:
        Merged graph
    """
    merged = nx.Graph()

    for graph in graphs:
        merged = nx.compose(merged, graph)

    return merged


def get_graph_summary(graph: nx.Graph) -> dict:
    """
    Get basic statistics about a graph.

    Args:
        graph: NetworkX graph

    Returns:
        Dictionary with graph statistics
    """
    return {
        "num_nodes": graph.number_of_nodes(),
        "num_edges": graph.number_of_edges(),
        "is_connected": nx.is_connected(graph) if len(graph) > 0 else False,
        "num_components": nx.number_connected_components(graph),
        "density": nx.density(graph) if len(graph) > 0 else 0,
    }
