from blends.models import (
    Graph,
    NId,
)
from blends.query import (
    adj_ast,
    get_node_by_path,
    match_ast_d,
    match_ast_group,
)
from blends.syntax.builders.class_decl import (
    build_class_node,
)
from blends.syntax.metadata.java import (
    add_class_to_metadata,
)
from blends.syntax.models import (
    SyntaxGraphArgs,
)
from blends.utilities.text_nodes import (
    node_to_str,
)


def extract_modifiers(graph: Graph, n_id: NId) -> tuple[NId | None, str | None]:
    modifiers_id = match_ast_d(graph, n_id, "modifiers")
    if not modifiers_id:
        return None, None

    access_modifiers: str | None = None
    annotation_ids_raw = match_ast_group(graph, modifiers_id, "annotation", "marker_annotation")
    annotation_ids = annotation_ids_raw["annotation"] + annotation_ids_raw["marker_annotation"]

    keyword_ids = [c for c in adj_ast(graph, modifiers_id) if c not in annotation_ids]
    if len(annotation_ids) == 0:
        modifiers_id = None

    if keyword_ids:
        access_modifiers = " ".join(graph.nodes[c].get("label_text", "") for c in keyword_ids)
    return modifiers_id, access_modifiers


def reader(args: SyntaxGraphArgs) -> NId:
    graph = args.ast_graph
    class_node = args.ast_graph.nodes[args.n_id]
    name_id = class_node["label_field_name"]
    block_id = class_node["label_field_body"]
    name = node_to_str(graph, name_id)

    inherited_class: str | None = None
    if extends_id := get_node_by_path(graph, args.n_id, "superclass", "type_identifier"):
        inherited_class = graph.nodes[extends_id].get("label_text", None)

    if (
        implements_id := get_node_by_path(
            graph,
            args.n_id,
            "super_interfaces",
            "type_list",
            "type_identifier",
        )
    ) and (implements_value := graph.nodes[implements_id].get("label_text")):
        if inherited_class is not None:
            inherited_class = f"{inherited_class},{implements_value}"
        else:
            inherited_class = implements_value

    if args.syntax_graph.nodes.get(NId(0)):
        add_class_to_metadata(args, name)

    modifiers_id, access_modifiers = extract_modifiers(graph, args.n_id)

    return build_class_node(
        args,
        name,
        block_id,
        None,
        inherited_class,
        modifiers_id,
        access_modifiers,
    )
