import os
import re
import sys


def split_params(param_string: str):
    """Split parameters on commas while ignoring nested structures."""
    params = []
    current: list[str] = []
    stack: list[str] = []
    pairs = {')': '(', ']': '[', '}': '{'}
    in_quote = None
    escape = False
    for char in param_string:
        if escape:
            current.append(char)
            escape = False
            continue

        if char == "\\":
            current.append(char)
            escape = True
            continue

        if in_quote:
            current.append(char)
            if char == in_quote:
                in_quote = None
            continue

        if char in "'\"":
            current.append(char)
            in_quote = char
            continue
        
        if char in '([{':
            stack.append(char)
        elif char in ')]}':
            if stack and stack[-1] == pairs.get(char):
                stack.pop()
            else:
                raise ValueError("unbalance in delimiter")
        
        if char == ',' and not stack:
            params.append(''.join(current).strip())
            current = []
        else:
            current.append(char)

    if stack:
        raise ValueError("unbalance in delimiter")
    if in_quote:
        raise ValueError(f"Unclosed quote: {in_quote}")

    params.append(''.join(current).strip())
    params = [p for p in params if p]
    return params

EXCLUDED_DIRS = {"addons", ".git", ".github"}

single_char_vars = []

# Patterns reused from check_gd_nomenclature.py
VAR_PATTERN = re.compile(r"(?:@\w+\s+)*var\s+([A-Za-z0-9_]+)")
FUNC_PATTERN = re.compile(r"func\s+[A-Za-z0-9_]+\s*(\([^)]*\))?")
FOR_PATTERN = re.compile(r"for\s+([A-Za-z0-9_]+)(?:\s*:\s*[^\s]+)?\s+in\b")

for root, dirs, files in os.walk('.', topdown=True):
    rel_root = os.path.relpath(root, '.')
    if any(rel_root == ex or rel_root.startswith(f"{ex}{os.sep}") for ex in EXCLUDED_DIRS):
        dirs[:] = []
        continue
    for fname in files:
        if fname.endswith('.gd'):
            path = os.path.join(root, fname)
            try:
                with open(path, 'r', encoding='utf-8') as f:
                    lines = f.readlines()
            except Exception as e:
                continue
            for idx, line in enumerate(lines, 1):
                stripped = line.strip()
                if stripped.startswith('#') or not stripped:
                    continue

                match_var = VAR_PATTERN.match(stripped)
                if match_var:
                    name = match_var.group(1)
                    if len(name) == 1:
                        single_char_vars.append((path, idx, name))

                match_func = FUNC_PATTERN.match(stripped)
                if match_func:
                    params = match_func.group(1)
                    if params:
                        params = params.strip('()')
                        for param in split_params(params):
                            param_name = param.split(':')[0].split('=')[0].strip()
                            if param_name and len(param_name) == 1:
                                single_char_vars.append((path, idx, param_name))

                match_for = FOR_PATTERN.match(stripped)
                if match_for:
                    name = match_for.group(1)
                    if len(name) == 1:
                        single_char_vars.append((path, idx, name))

if single_char_vars:
    print("### \u274c Single Character Variable Check Failed\n")
    print(f"Variables and functions must not have a name of a single character, they must be more explicit.\nFound {len(single_char_vars)} single-character name{'s' if len(single_char_vars) > 1 else ''}:\n")
    for path, idx, name in single_char_vars:
        print(f"- `{path}:{idx}` variable `{name}`")
    sys.exit(1)
else:
    print("\u2705 No single-character variable names found.")
