def count_resolved(rules_dir, rule_name, key):
    """Count entries in resolved rule field"""
    try:
        resolved = _rule_resolve_internal(rules_dir, rule_name)
        print(len(resolved.get(key, [])))
    except:
        print(0)

def _rule_resolve_internal(rules_dir, rule_name, visited=None):
    """Internal recursive resolver — returns dict, does not print"""
    if visited is None:
        visited = set()
    if rule_name in visited:
        raise ValueError(f"Circular dependency detected: {rule_name}")
    visited.add(rule_name)

    rule_file = find_rule_file(rules_dir, rule_name)
    with open(rule_file) as f:
        rule = json.load(f)

    merged = {
        'allow_ips':    [],
        'allow_ports':  [],
        'block_ips':    [],
        'block_ports':  [],
        'dns_redirect': False
    }

    for base_name in rule.get('extends', []):
        base = _rule_resolve_internal(rules_dir, base_name, visited.copy())
        merged['allow_ips']   += base.get('allow_ips', [])
        merged['allow_ports'] += base.get('allow_ports', [])
        merged['block_ips']   += base.get('block_ips', [])
        merged['block_ports'] += base.get('block_ports', [])
        if base.get('dns_redirect'):
            merged['dns_redirect'] = True

    # Merge own fields — use .get() with defaults for all fields
    merged['allow_ips']   = list(dict.fromkeys(
        merged['allow_ips']   + rule.get('allow_ips', [])))
    merged['allow_ports'] = list(dict.fromkeys(
        merged['allow_ports'] + rule.get('allow_ports', [])))
    merged['block_ips']   = list(dict.fromkeys(
        merged['block_ips']   + rule.get('block_ips', [])))
    merged['block_ports'] = list(dict.fromkeys(
        merged['block_ports'] + rule.get('block_ports', [])))
    if rule.get('dns_redirect', False):
        merged['dns_redirect'] = True

    merged['name']    = rule.get('name', rule_name)
    merged['desc']    = rule.get('desc', '')
    merged['group']   = rule.get('group', '')
    merged['extends'] = rule.get('extends', [])
    return merged