import sys
import re

def parse_stream(stream_text):
    # Splits the stream by our custom file delimiters
    files = {}
    parts = re.split(r'=== FILE: (.*?) ===\n', stream_text)
    
    # The first part is the original monolithic file
    if parts:
        files['original'] = parts[0]
        
    for i in range(1, len(parts), 2):
        filename = parts[i]
        content = parts[i+1] if i+1 < len(parts) else ""
        files[filename] = content
        
    return files

def strip_comments(text):
    text = re.sub(r'/\*.*?\*/', '', text, flags=re.DOTALL)
    text = re.sub(r'//.*', '', text)
    return text

def extract_declarations(text):
    clean = strip_comments(text)
    
    # Matches method/function declarations inside a class in Dart
    # e.g., void myMethod(..., Future<void> myMethod(..., myMethod(..., get myProp, set myProp
    # We look for word followed by ( or get/set followed by word.
    method_decl_pattern = re.compile(
        r'(?:[a-zA-Z0-9_<>\?\[\]]+(?:\s+[a-zA-Z0-9_<>\?\[\]]+)*\s+)?([a-zA-Z0-9_]+)\s*\([^\)]*\)\s*(?:async)?\s*(?:=>|\{)'
    )
    
    methods = set()
    for match in method_decl_pattern.finditer(clean):
        method_name = match.group(1)
        if method_name not in keywords and not method_name.isdigit():
            methods.add(method_name)
            
    # Also extract getters and setters
    getset_pattern = re.compile(r'\b(?:get|set)\s+([a-zA-Z0-9_]+)\b')
    for match in getset_pattern.finditer(clean):
        name = match.group(1)
        if name not in keywords:
            methods.add(name)
            
    # Extract variables/fields declarations
    var_decl_pattern = re.compile(
        r'\b(?:var|final|const|late|RxBool|RxInt|RxDouble|RxString|RxList|RxMap|RxSet|Rx|String|int|double|bool|List|Map|Set|Timer|LatLng|Position|SiroMapController)\??\s+([a-zA-Z0-9_]+)\b'
    )
    
    variables = set()
    for match in var_decl_pattern.finditer(clean):
        var_name = match.group(1)
        if var_name not in keywords and not var_name.isdigit():
            variables.add(var_name)
            
    return methods, variables

keywords = {
    'if', 'for', 'while', 'switch', 'catch', 'super', 'await', 'print',
    'assert', 'dynamic', 'void', 'return', 'with', 'override', 'get', 'set',
    'class', 'import', 'extends', 'implements', 'mixin', 'this', 'else', 'try',
    'final', 'const', 'var', 'late', 'static', 'factory', 'new', 'abstract',
    'covariant', 'external', 'operator', 'part', 'required', 'typedef', 'yield'
}

def main():
    stream_text = sys.stdin.read()
    files = parse_stream(stream_text)
    
    orig_content = files.get('original', '')
    split_contents = {k: v for k, v in files.items() if k != 'original'}
    
    orig_methods, orig_vars = extract_declarations(orig_content)
    
    # Combined declarations in split files
    split_methods = set()
    split_vars = set()
    for filename, content in split_contents.items():
        m, v = extract_declarations(content)
        split_methods.update(m)
        split_vars.update(v)
        
    missing_methods = sorted(orig_methods - split_methods)
    missing_vars = sorted(orig_vars - split_vars)
    
    print("--- PRECISE MISSING METHODS ---")
    print(f"Total original methods/getters/setters: {len(orig_methods)}")
    print(f"Total defined in split controllers: {len(split_methods)}")
    print(f"Total missing: {len(missing_methods)}")
    for m in missing_methods:
        print(f" - {m}")
        
    print("\n--- PRECISE MISSING VARIABLES/FIELDS ---")
    print(f"Total original variables: {len(orig_vars)}")
    print(f"Total defined in split controllers: {len(split_vars)}")
    print(f"Total missing: {len(missing_vars)}")
    for v in missing_vars:
        print(f" - {v}")

if __name__ == '__main__':
    main()
