from __future__ import annotations

from pydantic import BaseModel

from solutions.graph.models import (
    DeletingNodeWithDepedentEdgesError,
    EdgeGroupId,
    GraphId,
    ModelValidationError,
    NodeGroupId,
    VersionedGraphMetadata,
)
from stores.graph_metadata_store import GraphMetadataStore


class NodeParams(BaseModel):
    graph_id: GraphId
    node_id: NodeGroupId
    ref_version_token: str


def delete_node_group(store: GraphMetadataStore, params: NodeParams) -> VersionedGraphMetadata:
    """
    Raises:
        ModelValidationError
        GraphDoesNotExistError
        ConcurrentUpdateCollisionError
        DeletingNodeWithDepedentEdgesError
        GraphMetadataStoreError
    """
    graph_id = params.graph_id
    group_id = params.node_id

    graph_metadata = store.get(graph_id)

    if group_id not in list(graph_metadata["nodes"].keys()):
        raise ModelValidationError(f"Node group '{group_id}' does not exist.")

    node_group = graph_metadata["nodes"][group_id]["node_group"]

    for edge in graph_metadata["edges"].values():
        if edge["source_node_id"] == group_id or edge["target_node_id"] == group_id:
            raise DeletingNodeWithDepedentEdgesError(node_group, edge["edge_group"])

    graph_metadata["nodes"].pop(group_id)
    graph_metadata["nodes_view"].pop(group_id)
    new_graph_metadata = store.update(graph_metadata, params.ref_version_token)

    return new_graph_metadata


class EdgeParams(BaseModel):
    graph_id: GraphId
    edge_id: EdgeGroupId
    ref_version_token: str


def delete_edge_group(store: GraphMetadataStore, params: EdgeParams) -> VersionedGraphMetadata:
    """
    Raises:
        ModelValidationError
        GraphDoesNotExistError
        ConcurrentUpdateCollisionError
        GraphMetadataStoreError
    """
    graph_id = params.graph_id
    group_id = params.edge_id

    graph_metadata = store.get(graph_id)

    if group_id not in list(graph_metadata["edges"].keys()):
        raise ModelValidationError(f"Edge group '{group_id}' does not exist.")

    graph_metadata["edges"].pop(group_id)
    graph_metadata["edges_view"].pop(group_id)
    new_grapH_metadata = store.update(graph_metadata, params.ref_version_token)

    return new_grapH_metadata
