import re
import json
from typing import Any, Dict, List, Tuple, Optional
from sari.core.parsers.base import BaseHandler

class JavaHandler(BaseHandler):
    def handle_node(self, node: Any, get_t, find_id, ext: str, p_meta: Dict[str, Any]) -> Tuple[Optional[str], Optional[str], Dict[str, Any], bool]:
        n_type = node.type
        meta = {
            "annotations": [], "generated": False, "reactive": False, 
            "extends": [], "framework_role": "", "return_type": "", "api": False
        }
        
        meta["annotations"] = self._extract_annotations_ast(node, get_t)

        if n_type in ("class_declaration", "interface_declaration", "enum_declaration", "record_declaration", "object_declaration"):
            # Use pure identifier preference for reliable name extraction
            name = find_id(node, prefer_pure_identifier=True)
            txt = get_t(node)
            
            # Inheritance
            for c in node.children:
                if c.type in ("superclass", "extends_interfaces", "interfaces"):
                    meta["extends"].extend(re.findall(r"[A-Z][a-zA-Z0-9_]*", get_t(c)))
            
            # Framework Logic
            if any("EntityPathBase" in x for x in meta["extends"]) or (name and name.startswith("Q")):
                meta["generated"] = True
                meta["framework"] = "QueryDSL"
            
            if "JpaRepository" in txt or "JpaRepository" in str(meta["extends"]): meta["framework_role"] = "Repository"
            if any(a in meta["annotations"] for a in ("RestController", "Controller")): meta["framework_role"] = "Controller"
            if "Service" in meta["annotations"]: meta["framework_role"] = "Service"
            if "Configuration" in meta["annotations"]: meta["framework_role"] = "Config"
            
            return "class", name, meta, True

        if n_type in ("method_declaration", "constructor_declaration"):
            name = find_id(node, prefer_pure_identifier=True)
            txt = get_t(node)
            
            for c in node.children:
                if c.type in ("type_identifier", "generic_type", "void_type", "boolean_type"):
                    meta["return_type"] = get_t(c)
                    break
            
            if any(r in txt for r in ("Mono", "Flux")): meta["reactive"] = True
            
            # API detection is handled by extract_api_info, but flag it here too
            if any(a in meta["annotations"] for a in ("GetMapping", "PostMapping", "RequestMapping", "Bean")):
                meta["api"] = True
                
            return "method", name, meta, True

        return None, None, {}, False

    def _extract_annotations_ast(self, node: Any, get_t) -> List[str]:
        annos = []
        modifiers = None
        for c in node.children:
            if c.type == "modifiers": modifiers = c; break
        
        if modifiers:
            for c in modifiers.children:
                if c.type in ("marker_annotation", "annotation"):
                    for cc in c.children:
                        if cc.type in ("identifier", "scoped_identifier"):
                            annos.append(get_t(cc))
                            break
        return annos

    def extract_api_info(self, node: Any, get_t, get_child) -> Dict:
        """Restored from backup: Extracts HTTP method/path from annotations."""
        res = {"http_path": None, "http_methods": []}
        modifiers = get_child(node, "modifiers")
        if not modifiers: return res

        for c in modifiers.children:
            if c.type in ("marker_annotation", "annotation"):
                ann_id = get_child(c, "identifier", "scoped_identifier")
                if ann_id:
                    ann_name = get_t(ann_id)
                    if ann_name in ("GetMapping", "PostMapping", "PutMapping", "DeleteMapping", "PatchMapping", "RequestMapping"):
                        if ann_name != "RequestMapping":
                            res["http_methods"].append(ann_name.replace("Mapping", "").upper())
                        
                        # Extract path argument
                        args = get_child(c, "annotation_argument_list", "arguments")
                        if args:
                            for arg in args.children:
                                if arg.type == "string_literal":
                                    res["http_path"] = get_t(arg).strip("'\"")
                                elif arg.type == "assignment_expression":
                                    left = get_child(arg, "identifier")
                                    if left and get_t(left) in ("value", "path"):
                                        right = get_child(arg, "string_literal")
                                        if right: res["http_path"] = get_t(right).strip("'\"")
        return res
