import posixpath
import re

from blends.models import NId
from blends.stack.edges import Edge, add_edge
from blends.stack.node_helpers import push_symbol_node_attributes
from blends.syntax.builders.utils import get_next_synthetic_node_id, get_or_create_root_nid
from blends.syntax.models import SyntaxGraphArgs

_FILE_EXTENSIONS = frozenset({".dart", ".rb", ".py", ".js", ".jsx", ".ts", ".tsx", ".php"})
_SEGMENT_SEPARATOR = re.compile(r"[./]")


def _is_file_path(expression: str) -> bool:
    return "/" in expression or expression.count(".") == 1


def _strip_file_extension(name: str) -> str:
    if not _is_file_path(name):
        return name
    _, ext = posixpath.splitext(name)
    if ext.lower() in _FILE_EXTENSIONS:
        return name[: -len(ext)]
    return name


def extract_module_stem(expression: str) -> str:
    cleaned = _strip_file_extension(expression)
    parts = [p for p in _SEGMENT_SEPARATOR.split(cleaned) if p and p != "*"]
    return parts[-1] if parts else cleaned


def build_import_reference_chain_to_root(
    args: SyntaxGraphArgs,
    module_name: str,
    source_node_id: NId,
) -> None:
    if not module_name:
        return
    root_nid = get_or_create_root_nid(args)
    push_id = get_next_synthetic_node_id(args)
    args.syntax_graph.add_node(
        push_id,
        label_type="SyntheticImportRef",
        **push_symbol_node_attributes(symbol=module_name, is_reference=False),
    )
    add_edge(args.syntax_graph, Edge(source=source_node_id, sink=push_id))
    add_edge(args.syntax_graph, Edge(source=push_id, sink=root_nid))
