#!/usr/bin/env python3
"""
NovaLang Runtime - Execution Engine with Real Code Execution
Handles variables, functions, classes, control flow, and database operations
"""

import os
import sys
import re
import sqlite3
import glob
from typing import Dict, List, Any, Optional, Callable
from dataclasses import dataclass, field
from pathlib import Path

# Try to import config reader
try:
    from .config_reader import NovaLangConfig
    HAS_CONFIG = True
except ImportError:
    HAS_CONFIG = False

# Try to import MySQL connector
try:
    import mysql.connector
    HAS_MYSQL = True
except ImportError:
    HAS_MYSQL = False

@dataclass
class Scope:
    """Variable scope management"""
    variables: Dict[str, Any] = field(default_factory=dict)
    parent: Optional['Scope'] = None
    
    def get(self, name: str) -> Any:
        if name in self.variables:
            return self.variables[name]
        if self.parent:
            return self.parent.get(name)
        raise NameError(f"Variable '{name}' not defined")
    
    def set(self, name: str, value: Any):
        self.variables[name] = value
    
    def exists(self, name: str) -> bool:
        return name in self.variables or (self.parent and self.parent.exists(name))

@dataclass
class NovaFunction:
    """Function object"""
    name: str
    parameters: List[str]
    body: List[str]
    scope: Scope

@dataclass
class NovaClass:
    """Class object"""
    name: str
    properties: Dict[str, Any]
    methods: Dict[str, NovaFunction]
    annotations: List[Dict[str, Any]]

class NovaLangRuntime:
    """Complete runtime for executing NovaLang code"""
    
    def __init__(self, config_path: str = "novalang.config", workspace_path: str = "."):
        self.global_scope = Scope()
        self.current_scope = self.global_scope
        self.functions: Dict[str, NovaFunction] = {}
        self.classes: Dict[str, NovaClass] = {}
        self.db_connection = None
        self.workspace_path = workspace_path
        
        # Spring Boot-style architecture components
        self.http_server = None
        self.repositories: Dict[str, Any] = {}
        self.services: Dict[str, Any] = {}
        self.controllers: Dict[str, Any] = {}
        self.enable_http_server = False
        
        # Load configuration
        if HAS_CONFIG and os.path.exists(config_path):
            self.config = NovaLangConfig(config_path)
            db_config = self.config.get_database_config()
            self.db_type = db_config['type'].lower()
            self.db_config = db_config
        else:
            self.config = None
            self.db_type = 'sqlite'
            self.db_config = {'name': 'novalang.db'}
        
        # Built-in functions
        self._setup_builtins()
    
    def _setup_builtins(self):
        """Setup built-in functions"""
        def print_func(*args):
            print(*args)
            return None
        
        def len_func(obj):
            return len(obj)
        
        def str_func(obj):
            return str(obj)
        
        def int_func(obj):
            return int(obj)
        
        def float_func(obj):
            return float(obj)
        
        self.global_scope.set('print', print_func)
        self.global_scope.set('len', len_func)
        self.global_scope.set('str', str_func)
        self.global_scope.set('int', int_func)
        self.global_scope.set('float', float_func)
    
    def execute_code(self, code: str) -> Any:
        """Execute NovaLang code"""
        lines = code.split('\n')
        return self._execute_lines(lines)
    
    def _execute_lines(self, lines: List[str]) -> Any:
        """Execute multiple lines of code"""
        i = 0
        result = None
        
        while i < len(lines):
            line = lines[i].strip()
            
            if not line or line.startswith('//'):
                i += 1
                continue
            
            # Handle class definitions
            if line.startswith('@') or (i + 1 < len(lines) and lines[i + 1].strip().startswith('class ')):
                i = self._handle_class_definition(lines, i)
                continue
            
            # Handle function definitions
            if line.startswith('function '):
                i = self._handle_function_definition(lines, i)
                continue
            
            # Handle variable declarations
            if line.startswith('let ') or line.startswith('const ') or line.startswith('var '):
                self._handle_variable_declaration(line)
                i += 1
                continue
            
            # Handle assignments
            if '=' in line and not line.startswith('//') and '==' not in line:
                self._handle_assignment(line)
                i += 1
                continue
            
            # Handle if statements
            if line.startswith('if '):
                i = self._handle_if_statement(lines, i)
                continue
            
            # Handle while loops
            if line.startswith('while '):
                i = self._handle_while_loop(lines, i)
                continue
            
            # Handle for loops
            if line.startswith('for '):
                i = self._handle_for_loop(lines, i)
                continue
            
            # Handle return statements
            if line.startswith('return '):
                return self._evaluate_expression(line[7:].strip())
            
            # Handle function calls
            if '(' in line and ')' in line:
                result = self._evaluate_expression(line)
                i += 1
                continue
            
            i += 1
        
        return result
    
    def _handle_class_definition(self, lines: List[str], start: int) -> int:
        """Handle class definition with annotations"""
        annotations = []
        i = start
        
        # Collect annotations
        while i < len(lines) and lines[i].strip().startswith('@'):
            ann_line = lines[i].strip()
            annotations.append(self._parse_annotation(ann_line))
            i += 1
        
        # Parse class line
        class_line = lines[i].strip()
        if not class_line.startswith('class '):
            return i + 1
        
        class_name = class_line.split()[1].split('{')[0].strip()
        
        # Find class body
        brace_count = 0
        class_body_start = i
        for j in range(i, len(lines)):
            brace_count += lines[j].count('{') - lines[j].count('}')
            if brace_count == 0 and j > i:
                class_body_end = j
                break
        else:
            class_body_end = len(lines)
        
        # Create class object
        nova_class = NovaClass(
            name=class_name,
            properties={},
            methods={},
            annotations=annotations
        )
        
        self.classes[class_name] = nova_class
        
        # Handle database entity classes
        if any(ann['name'] == 'DatabaseEntity' for ann in annotations):
            self._create_database_table(nova_class, lines[class_body_start:class_body_end + 1])
        
        return class_body_end + 1
    
    def _parse_annotation(self, annotation_line: str) -> Dict[str, Any]:
        """Parse annotation with proper handling of quoted strings"""
        annotation_line = annotation_line[1:]  # Remove @
        if '(' in annotation_line:
            name = annotation_line.split('(')[0]
            params_str = annotation_line.split('(', 1)[1].rstrip(')')
            params = {}
            
            # Enhanced parsing: handle quoted strings with commas/parentheses
            import re
            # Match key: "value" pairs (quoted strings preserve everything inside)
            quoted_pairs = re.findall(r'(\w+):\s*"([^"]*)"', params_str)
            for key, val in quoted_pairs:
                params[key.strip()] = val
            
            # Also handle unquoted values for backwards compatibility
            unquoted_pairs = re.findall(r'(\w+):\s*([^,)"\s]+)', params_str)
            for key, val in unquoted_pairs:
                if key not in params:  # Don't override quoted values
                    params[key.strip()] = val.strip()
            
            return {'name': name, 'params': params}
        return {'name': annotation_line, 'params': {}}
    
    def _create_database_table(self, nova_class: NovaClass, class_body: List[str]):
        """Create actual database table from annotations"""
        # Get table name
        table_name = nova_class.name.lower()
        for ann in nova_class.annotations:
            if ann['name'] == 'Table' and 'name' in ann['params']:
                table_name = ann['params']['name']
        
        # Parse properties to build CREATE TABLE
        columns = []
        primary_key_column = None
        
        i = 0
        pending_annotations = []
        
        while i < len(class_body):
            line = class_body[i].strip()
            
            # Collect annotations
            if line.startswith('@'):
                ann = self._parse_annotation(line)
                pending_annotations.append(ann)
                i += 1
                continue
            
            # Process property with collected annotations
            if ('let ' in line or 'const ' in line) and pending_annotations:
                prop_name = line.replace('let ', '').replace('const ', '').split(':')[0].strip()
                
                # Extract column info
                col_name = prop_name
                col_type = 'TEXT'
                is_primary_key = False
                
                for ann in pending_annotations:
                    if ann['name'] == 'Column':
                        col_name = ann['params'].get('name', prop_name)
                        col_type = ann['params'].get('type', 'TEXT')
                    elif ann['name'] == 'PrimaryKey':
                        is_primary_key = True
                
                # Add column
                columns.append(f"{col_name} {col_type}")
                
                # Track primary key
                if is_primary_key:
                    primary_key_column = col_name
                
                # Clear pending annotations
                pending_annotations = []
            
            i += 1
        
        # Create table
        if columns:
            self._ensure_db_connection()
            
            # Add PRIMARY KEY constraint if specified
            if primary_key_column:
                # Find and modify the primary key column
                for idx, col in enumerate(columns):
                    if col.startswith(primary_key_column + ' '):
                        columns[idx] = col + ' PRIMARY KEY'
                        break
            
            create_sql = f"CREATE TABLE IF NOT EXISTS {table_name} ({', '.join(columns)})"
            
            try:
                cursor = self.db_connection.cursor()
                cursor.execute(create_sql)
                self.db_connection.commit()
                cursor.close()
                print(f"[OK] Created table: {table_name}")
            except Exception as e:
                print(f"[ERROR] Database error: {e}")
                print(f"[DEBUG] SQL was: {create_sql}")
    
    def _ensure_db_connection(self):
        """Ensure database connection exists"""
        if not self.db_connection:
            if self.db_type == 'mysql':
                if not HAS_MYSQL:
                    print("⚠️  MySQL support not available. Install: pip install mysql-connector-python")
                    print("   Falling back to SQLite")
                    self.db_type = 'sqlite'
                    self.db_connection = sqlite3.connect('novalang_fallback.db')
                else:
                    try:
                        self.db_connection = mysql.connector.connect(
                            host=self.db_config.get('host', 'localhost'),
                            port=self.db_config.get('port', 3306),
                            user=self.db_config.get('username', 'root'),
                            password=self.db_config.get('password', ''),
                            database=self.db_config.get('name', 'novalang')
                        )
                        print(f"📦 Connected to MySQL database: {self.db_config.get('name')}@{self.db_config.get('host')}")
                    except Exception as e:
                        print(f"⚠️  MySQL connection failed: {e}")
                        print("   Falling back to SQLite")
                        self.db_type = 'sqlite'
                        self.db_connection = sqlite3.connect('novalang_fallback.db')
            else:
                # SQLite (default)
                db_name = self.db_config.get('name', 'novalang.db')
                self.db_connection = sqlite3.connect(db_name)
                print(f"📦 Connected to SQLite database: {db_name}")
    
    def _handle_function_definition(self, lines: List[str], start: int) -> int:
        """Handle function definition"""
        func_line = lines[start].strip()
        
        # Parse: function name(params) {
        name = func_line.split('(')[0].replace('function ', '').strip()
        params_str = func_line.split('(')[1].split(')')[0]
        # Parse parameters, removing type annotations
        parameters = []
        for p in params_str.split(','):
            p = p.strip()
            if p:
                # Remove type annotation (e.g., "a: number" -> "a")
                param_name = p.split(':')[0].strip()
                parameters.append(param_name)
        
        # Find function body
        brace_count = 0
        func_body = []
        i = start
        
        for j in range(start, len(lines)):
            line = lines[j]
            brace_count += line.count('{') - line.count('}')
            if j > start:
                func_body.append(line)
            if brace_count == 0 and j > start:
                break
        
        # Store function
        self.functions[name] = NovaFunction(
            name=name,
            parameters=parameters,
            body=func_body,
            scope=self.current_scope
        )
        
        return j + 1
    
    def _handle_variable_declaration(self, line: str):
        """Handle variable declaration"""
        # let name: type = value
        line = line.replace('let ', '').replace('const ', '').replace('var ', '')
        
        if '=' in line:
            name_part, value_part = line.split('=', 1)
            name = name_part.split(':')[0].strip()
            value = self._evaluate_expression(value_part.strip())
            self.current_scope.set(name, value)
        else:
            name = line.split(':')[0].strip()
            self.current_scope.set(name, None)
    
    def _handle_assignment(self, line: str):
        """Handle variable assignment"""
        if '=' in line:
            name, value_part = line.split('=', 1)
            name = name.strip()
            value = self._evaluate_expression(value_part.strip())
            self.current_scope.set(name, value)
    
    def _handle_if_statement(self, lines: List[str], start: int) -> int:
        """Handle if statement"""
        if_line = lines[start].strip()
        condition_str = if_line.replace('if ', '').replace('(', '').replace(')', '').replace('{', '').strip()
        condition = self._evaluate_expression(condition_str)
        
        # Find if body
        brace_count = 0
        if_body = []
        i = start
        
        for j in range(start, len(lines)):
            line = lines[j]
            brace_count += line.count('{') - line.count('}')
            if j > start and brace_count > 0:
                if_body.append(line)
            if brace_count == 0 and j > start:
                i = j
                break
        
        # Execute if body if condition is true
        if condition:
            self._execute_lines(if_body)
        
        # Check for else
        if i + 1 < len(lines) and lines[i + 1].strip().startswith('else'):
            i += 1
            # Find else body
            else_body = []
            brace_count = 0
            for j in range(i, len(lines)):
                line = lines[j]
                brace_count += line.count('{') - line.count('}')
                if j > i and brace_count > 0:
                    else_body.append(line)
                if brace_count == 0 and j > i:
                    i = j
                    break
            
            if not condition:
                self._execute_lines(else_body)
        
        return i + 1
    
    def _handle_while_loop(self, lines: List[str], start: int) -> int:
        """Handle while loop"""
        while_line = lines[start].strip()
        condition_str = while_line.replace('while ', '').replace('(', '').replace(')', '').replace('{', '').strip()
        
        # Find while body
        brace_count = 0
        while_body = []
        i = start
        
        for j in range(start, len(lines)):
            line = lines[j]
            brace_count += line.count('{') - line.count('}')
            if j > start and brace_count > 0:
                while_body.append(line)
            if brace_count == 0 and j > start:
                i = j
                break
        
        # Execute while body while condition is true
        max_iterations = 10000  # Safety limit
        iterations = 0
        while self._evaluate_expression(condition_str) and iterations < max_iterations:
            self._execute_lines(while_body)
            iterations += 1
        
        return i + 1
    
    def _handle_for_loop(self, lines: List[str], start: int) -> int:
        """Handle for loop"""
        for_line = lines[start].strip()
        # for (let i = 0; i < 10; i++) or for item in array
        
        # Find for body
        brace_count = 0
        for_body = []
        i = start
        
        for j in range(start, len(lines)):
            line = lines[j]
            brace_count += line.count('{') - line.count('}')
            if j > start and brace_count > 0:
                for_body.append(line)
            if brace_count == 0 and j > start:
                i = j
                break
        
        # Simple for loop: for (let i = 0; i < 10; i++)
        if '=' in for_line and ';' in for_line:
            parts = for_line.replace('for ', '').replace('(', '').replace(')', '').strip().split(';')
            if len(parts) == 3:
                init = parts[0].strip()
                condition = parts[1].strip()
                increment = parts[2].strip()
                
                # Execute init
                self._handle_variable_declaration(init)
                
                # Execute loop
                max_iterations = 10000
                iterations = 0
                while self._evaluate_expression(condition) and iterations < max_iterations:
                    self._execute_lines(for_body)
                    # Execute increment
                    if '++' in increment:
                        var_name = increment.replace('++', '').strip()
                        current = self.current_scope.get(var_name)
                        self.current_scope.set(var_name, current + 1)
                    else:
                        self._evaluate_expression(increment)
                    iterations += 1
        
        return i + 1
    
    def _evaluate_expression(self, expr: str) -> Any:
        """Evaluate an expression"""
        expr = expr.strip()
        
        if not expr:
            return None
        
        # String literals
        if (expr.startswith('"') and expr.endswith('"')) or (expr.startswith("'") and expr.endswith("'")):
            return expr[1:-1]
        
        # Number literals
        if expr.replace('.', '').replace('-', '').isdigit():
            return float(expr) if '.' in expr else int(expr)
        
        # Boolean literals
        if expr == 'true':
            return True
        if expr == 'false':
            return False
        if expr == 'null':
            return None
        
        # Function calls
        if '(' in expr and ')' in expr:
            func_name = expr.split('(')[0].strip()
            args_str = expr.split('(')[1].rsplit(')', 1)[0]
            args = [self._evaluate_expression(arg.strip()) for arg in args_str.split(',') if arg.strip()]
            
            # Built-in functions
            if self.current_scope.exists(func_name):
                func = self.current_scope.get(func_name)
                if callable(func):
                    return func(*args)
            
            # User-defined functions
            if func_name in self.functions:
                return self._call_function(self.functions[func_name], args)
        
        # Binary operations
        if ' + ' in expr:
            left, right = expr.split(' + ', 1)
            left_val = self._evaluate_expression(left)
            right_val = self._evaluate_expression(right)
            # String concatenation - convert to string if either is string
            if isinstance(left_val, str) or isinstance(right_val, str):
                return str(left_val) + str(right_val)
            return left_val + right_val
        if ' - ' in expr:
            left, right = expr.split(' - ', 1)
            return self._evaluate_expression(left) - self._evaluate_expression(right)
        if ' * ' in expr:
            left, right = expr.split(' * ', 1)
            return self._evaluate_expression(left) * self._evaluate_expression(right)
        if ' / ' in expr:
            left, right = expr.split(' / ', 1)
            return self._evaluate_expression(left) / self._evaluate_expression(right)
        
        # Comparisons
        if ' == ' in expr:
            left, right = expr.split(' == ', 1)
            return self._evaluate_expression(left) == self._evaluate_expression(right)
        if ' != ' in expr:
            left, right = expr.split(' != ', 1)
            return self._evaluate_expression(left) != self._evaluate_expression(right)
        if ' < ' in expr:
            left, right = expr.split(' < ', 1)
            return self._evaluate_expression(left) < self._evaluate_expression(right)
        if ' > ' in expr:
            left, right = expr.split(' > ', 1)
            return self._evaluate_expression(left) > self._evaluate_expression(right)
        if ' <= ' in expr:
            left, right = expr.split(' <= ', 1)
            return self._evaluate_expression(left) <= self._evaluate_expression(right)
        if ' >= ' in expr:
            left, right = expr.split(' >= ', 1)
            return self._evaluate_expression(left) >= self._evaluate_expression(right)
        
        # Logical operations
        if ' && ' in expr:
            left, right = expr.split(' && ', 1)
            return self._evaluate_expression(left) and self._evaluate_expression(right)
        if ' || ' in expr:
            left, right = expr.split(' || ', 1)
            return self._evaluate_expression(left) or self._evaluate_expression(right)
        
        # Increment/decrement
        if expr.endswith('++'):
            var_name = expr[:-2].strip()
            value = self.current_scope.get(var_name)
            self.current_scope.set(var_name, value + 1)
            return value + 1
        if expr.endswith('--'):
            var_name = expr[:-2].strip()
            value = self.current_scope.get(var_name)
            self.current_scope.set(var_name, value - 1)
            return value - 1
        
        # Variable reference
        if self.current_scope.exists(expr):
            return self.current_scope.get(expr)
        
        # Try to evaluate as Python expression (fallback)
        try:
            return eval(expr, {"__builtins__": {}}, self.current_scope.variables)
        except:
            return expr
    
    def _call_function(self, func: NovaFunction, args: List[Any]) -> Any:
        """Call a user-defined function"""
        # Create new scope for function
        func_scope = Scope(parent=func.scope)
        
        # Bind parameters
        for i, param in enumerate(func.parameters):
            if i < len(args):
                func_scope.set(param, args[i])
        
        # Save current scope
        old_scope = self.current_scope
        self.current_scope = func_scope
        
        # Execute function body
        result = self._execute_lines(func.body)
        
        # Restore scope
        self.current_scope = old_scope
        
        return result
    
    def scan_and_create_entities(self, directory: str = "."):
        """Scan workspace for @DatabaseEntity classes and create tables"""
        print(f"🔍 Scanning for entities in {directory}...")
        
        # Find all .nova files
        nova_files = glob.glob(os.path.join(directory, "*.nova"))
        if not nova_files:
            print("⚠️  No .nova files found")
            return
        
        entities_found = 0
        tables_created = 0
        
        for file_path in nova_files:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                # Check if file contains @DatabaseEntity
                if '@DatabaseEntity' in content:
                    entities_found += 1
                    # Parse and create tables
                    if self._process_entity_file(content):
                        tables_created += 1
                        
            except Exception as e:
                print(f"⚠️  Error processing {file_path}: {e}")
        
        if entities_found > 0:
            print(f"✅ Found {entities_found} entities, created {tables_created} tables")
        else:
            print("ℹ️  No database entities found")
    
    def _process_entity_file(self, content: str) -> bool:
        """Process a file containing entity definitions"""
        lines = content.split('\n')
        
        for i, line in enumerate(lines):
            if '@DatabaseEntity' in line:
                # Collect annotations
                annotations = []
                j = i
                while j < len(lines) and (lines[j].strip().startswith('@') or not lines[j].strip()):
                    if lines[j].strip().startswith('@'):
                        ann = self._parse_annotation(lines[j].strip())
                        annotations.append(ann)
                    j += 1
                
                # Find class definition
                if j < len(lines) and 'class ' in lines[j]:
                    class_line = lines[j].strip()
                    class_name = class_line.replace('class ', '').split('{')[0].strip()
                    
                    # Find class body
                    class_body = []
                    brace_count = 0
                    for k in range(j, len(lines)):
                        brace_count += lines[k].count('{') - lines[k].count('}')
                        class_body.append(lines[k])
                        if brace_count == 0 and k > j:
                            break
                    
                    # Create class object
                    nova_class = NovaClass(
                        name=class_name,
                        properties={},
                        methods={},
                        annotations=annotations
                    )
                    
                    # Create table
                    self._create_database_table(nova_class, class_body)
                    return True
        
        return False
    
    def scan_spring_boot_structure(self, base_path: str = "."):
        """Scan Spring Boot-style directory structure"""
        print(f"🔍 Scanning Spring Boot-style project structure in {base_path}...")
        
        # Check for src/ directory
        src_path = os.path.join(base_path, "src")
        if not os.path.exists(src_path):
            print("ℹ️  No src/ directory found, using flat structure")
            return False
        
        # Scan directories
        entities_path = os.path.join(src_path, "entities")
        repositories_path = os.path.join(src_path, "repositories")
        services_path = os.path.join(src_path, "services")
        controllers_path = os.path.join(src_path, "controllers")
        
        entities_count = self._scan_entities(entities_path) if os.path.exists(entities_path) else 0
        repos_count = self._scan_repositories(repositories_path) if os.path.exists(repositories_path) else 0
        services_count = self._scan_services(services_path) if os.path.exists(services_path) else 0
        controllers_count = self._scan_controllers(controllers_path) if os.path.exists(controllers_path) else 0
        
        if entities_count > 0:
            print(f"   ├── Found {entities_count} entities in src/entities/")
        if repos_count > 0:
            print(f"   ├── Found {repos_count} repositories in src/repositories/")
        if services_count > 0:
            print(f"   ├── Found {services_count} services in src/services/")
        if controllers_count > 0:
            print(f"   └── Found {controllers_count} controllers in src/controllers/")
        
        return entities_count > 0 or controllers_count > 0
    
    def _scan_entities(self, path: str) -> int:
        """Scan and process entity files"""
        if not os.path.exists(path):
            return 0
        
        nova_files = glob.glob(os.path.join(path, "*.nova"))
        count = 0
        
        for file_path in nova_files:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                if '@DatabaseEntity' in content:
                    if self._process_entity_file(content):
                        # Auto-generate repository for this entity
                        import re
                        class_match = re.search(r'class\s+(\w+)', content)
                        table_match = re.search(r'@Table\(name:\s*"([^"]+)"\)', content)
                        
                        if class_match and table_match and self.db_connection:
                            entity_name = class_match.group(1)
                            table_name = table_match.group(1)
                            repo_name = entity_name + 'Repository'
                            
                            from .repository import RepositoryFactory
                            repo = RepositoryFactory.create_repository(
                                entity_name, table_name, self.db_connection
                            )
                            self.repositories[repo_name] = repo
                        
                        count += 1
            except Exception as e:
                print(f"⚠️  Error processing entity {file_path}: {e}")
        
        return count
    
    def _scan_repositories(self, path: str) -> int:
        """Scan repository files and generate implementations"""
        if not os.path.exists(path):
            return 0
        
        nova_files = glob.glob(os.path.join(path, "*.nova"))
        count = 0
        
        for file_path in nova_files:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                if '@Repository' in content:
                    self._process_repository_file(content, file_path)
                    count += 1
            except Exception as e:
                print(f"⚠️  Error processing repository {file_path}: {e}")
        
        return count
    
    def _scan_services(self, path: str) -> int:
        """Scan service files"""
        if not os.path.exists(path):
            return 0
        
        nova_files = glob.glob(os.path.join(path, "*.nova"))
        count = 0
        
        for file_path in nova_files:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                if '@Service' in content:
                    self._process_service_file(content, file_path)
                    count += 1
            except Exception as e:
                print(f"⚠️  Error processing service {file_path}: {e}")
        
        return count
    
    def _scan_controllers(self, path: str) -> int:
        """Scan controller files"""
        if not os.path.exists(path):
            return 0
        
        nova_files = glob.glob(os.path.join(path, "*.nova"))
        count = 0
        
        for file_path in nova_files:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                
                if '@RestController' in content:
                    self._process_controller_file(content, file_path)
                    count += 1
            except Exception as e:
                print(f"⚠️  Error processing controller {file_path}: {e}")
        
        return count
    
    def _process_repository_file(self, content: str, file_path: str):
        """Process repository file and create implementation"""
        # Extract repository class name
        import re
        class_match = re.search(r'class\s+(\w+)', content)
        if not class_match:
            return
        
        repo_name = class_match.group(1)
        
        # Extract entity type from file name (e.g., UserRepository -> User)
        entity_name = repo_name.replace('Repository', '')
        table_name = entity_name.lower() + 's'  # Simple pluralization
        
        # Create repository instance with auto-generated CRUD
        from .repository import RepositoryFactory
        if self.db_connection:
            repo_instance = RepositoryFactory.create_repository(
                entity_name, table_name, self.db_connection
            )
            self.repositories[repo_name] = repo_instance
    
    def _process_service_file(self, content: str, file_path: str):
        """Process service file"""
        import re
        class_match = re.search(r'class\s+(\w+)', content)
        if not class_match:
            return
        
        service_name = class_match.group(1)
        # Service processing - store for dependency injection
        self.services[service_name] = {'file': file_path, 'content': content}
    
    def _process_controller_file(self, content: str, file_path: str):
        """Process controller file and register routes"""
        import re
        
        # Extract controller class name
        class_match = re.search(r'class\s+(\w+)', content)
        if not class_match:
            return
        
        controller_name = class_match.group(1)
        
        # Extract @RequestMapping base path
        base_path = "/api"
        request_mapping = re.search(r'@RequestMapping\("([^"]+)"\)', content)
        if request_mapping:
            base_path = request_mapping.group(1)
        
        # Extract route methods
        routes = []
        
        # Find @GetMapping, @PostMapping, etc. (support empty paths with *)
        get_mappings = re.findall(r'@GetMapping\("([^"]*)"\)\s+def\s+(\w+)', content)
        for path, func_name in get_mappings:
            routes.append(('GET', base_path + path, func_name))
        
        post_mappings = re.findall(r'@PostMapping\("([^"]*)"\)\s+def\s+(\w+)', content)
        for path, func_name in post_mappings:
            routes.append(('POST', base_path + path, func_name))
        
        put_mappings = re.findall(r'@PutMapping\("([^"]*)"\)\s+def\s+(\w+)', content)
        for path, func_name in put_mappings:
            routes.append(('PUT', base_path + path, func_name))
        
        delete_mappings = re.findall(r'@DeleteMapping\("([^"]*)"\)\s+def\s+(\w+)', content)
        for path, func_name in delete_mappings:
            routes.append(('DELETE', base_path + path, func_name))
        
        patch_mappings = re.findall(r'@PatchMapping\("([^\"]*)"\)\s+def\s+(\w+)', content)
        for path, func_name in patch_mappings:
            routes.append(('PATCH', base_path + path, func_name))
        
        # Store controller info
        self.controllers[controller_name] = {
            'file': file_path,
            'content': content,
            'routes': routes
        }
        
        # Register routes with HTTP server if enabled
        if self.http_server and routes:
            for method, path, func_name in routes:
                # Create handler that executes real NovaLang controller method
                handler = self._create_controller_handler(controller_name, func_name, content)
                self.http_server.add_route(path, method, handler, controller_name, func_name)
    
    def _create_controller_handler(self, controller_name: str, func_name: str, content: str):
        """Create a handler that executes the actual NovaLang controller method"""
        def handler(**kwargs):
            try:
                # Extract the method code from controller using brace counting
                method_start_pattern = rf'def\s+{func_name}\s*\([^)]*\)\s*\{{'
                match = re.search(method_start_pattern, content)
                
                if not match:
                    return {'error': f'Method {func_name} not found', 'status': 500}
                
                # Find method body by counting braces
                start_pos = match.end()  # Position after opening brace
                brace_count = 1
                pos = start_pos
                
                while pos < len(content) and brace_count > 0:
                    if content[pos] == '{':
                        brace_count += 1
                    elif content[pos] == '}':
                        brace_count -= 1
                    pos += 1
                
                method_body = content[start_pos:pos-1]  # Exclude closing brace
                print(f"[DEBUG] Extracted method body length: {len(method_body)} chars")
                print(f"[DEBUG] Method body preview: {method_body[:200]}...")
                
                # Create execution context with injected dependencies
                context = {
                    'userRepository': self.repositories.get('UserRepository'),
                    'productRepository': self.repositories.get('ProductRepository'),
                    'orderRepository': self.repositories.get('OrderRepository'),
                    'userService': self.services.get('UserService'),
                    'productService': self.services.get('ProductService'),
                    'orderService': self.services.get('OrderService'),
                    'userData': kwargs.get('body', {}),  # Map body to userData parameter
                    'productData': kwargs.get('body', {}),  # Map body to productData parameter
                    'orderData': kwargs.get('body', {}),  # Map body to orderData parameter
                    'body': kwargs.get('body', {}),
                    'id': kwargs.get('id'),
                    'userId': kwargs.get('userId'),
                    'status': kwargs.get('status'),
                    'category': kwargs.get('category'),
                }
                
                # Execute NovaLang code (simplified execution)
                result = self._execute_controller_method(method_body, context)
                return result if result else {'success': True}
                
            except Exception as e:
                import traceback
                traceback.print_exc()
                return {'error': str(e), 'status': 500}
        
        return handler
    
    def _execute_controller_method(self, method_body: str, context: dict):
        """Execute NovaLang controller method code"""
        # Simple pattern matching for common operations
        lines = method_body.strip().split('\n')
        result = None
        
        # Debug logging
        print(f"[DEBUG] Executing controller method with {len(lines)} lines")
        print(f"[DEBUG] Context keys: {list(context.keys())}")
        print(f"[DEBUG] userData: {context.get('userData')}")
        
        for line in lines:
            line = line.strip()
            
            print(f"[DEBUG] Checking line: {line}")
            print(f"[DEBUG] .save( in line: {'.save(' in line}")
            print(f"[DEBUG] repository in line: {'repository' in line}")
            
            # Handle repository calls - CREATE/SAVE (matches: this.userRepository.save)
            if (('.save(' in line) or ('.create(' in line)) and (('Repository' in line) or ('repository' in line)):
                print(f"[DEBUG] Found save/create line: {line}")
                # Determine which repository
                repo = None
                data_key = None
                
                if 'userRepository' in line:
                    repo = context.get('userRepository')
                    data_key = 'userData'
                    print(f"[DEBUG] User repository: {repo is not None}")
                elif 'productRepository' in line:
                    repo = context.get('productRepository')
                    data_key = 'productData'
                elif 'orderRepository' in line:
                    repo = context.get('orderRepository')
                    data_key = 'orderData'
                
                if repo and data_key:
                    data = context.get(data_key, context.get('body', {}))
                    print(f"[DEBUG] Data to save: {data}")
                    if data:
                        created = repo.save(data)
                        print(f"[DEBUG] Saved successfully: {created}")
                        result = {'success': True, 'message': 'User created successfully', 'data': created, 'status': 201}
                else:
                    print(f"[DEBUG] No repo or data_key found")
                        
            # Handle findAll (matches: this.userRepository.findAll())
            elif (('.findAll()' in line) or ('.getAll()' in line)) and (('Repository' in line) or ('repository' in line)):
                if 'userRepository' in line and context.get('userRepository'):
                    data = context['userRepository'].find_all()
                    result = {'success': True, 'count': len(data), 'data': data}
                elif 'productRepository' in line and context.get('productRepository'):
                    data = context['productRepository'].find_all()
                    result = {'success': True, 'count': len(data), 'data': data}
                elif 'orderRepository' in line and context.get('orderRepository'):
                    data = context['orderRepository'].find_all()
                    result = {'success': True, 'count': len(data), 'data': data}
                    
            # Handle findById (matches: this.userRepository.findById)
            elif (('.findById(' in line) or ('.getById(' in line)) and (('Repository' in line) or ('repository' in line)):
                id_val = context.get('id')
                if id_val:
                    if 'userRepository' in line and context.get('userRepository'):
                        data = context['userRepository'].find_by_id(id_val)
                        if data:
                            result = {'success': True, 'data': data}
                        else:
                            result = {'success': False, 'error': 'Not found', 'status': 404}
                    elif 'productRepository' in line and context.get('productRepository'):
                        data = context['productRepository'].find_by_id(id_val)
                        if data:
                            result = {'success': True, 'data': data}
                        else:
                            result = {'success': False, 'error': 'Not found', 'status': 404}
                    elif 'orderRepository' in line and context.get('orderRepository'):
                        data = context['orderRepository'].find_by_id(id_val)
                        if data:
                            result = {'success': True, 'data': data}
                        else:
                            result = {'success': False, 'error': 'Not found', 'status': 404}
                            
            # Handle delete (matches: this.userRepository.delete or deleteById)
            elif (('.delete(' in line) or ('.deleteById(' in line)) and (('Repository' in line) or ('repository' in line)):
                id_val = context.get('id')
                if id_val:
                    if 'userRepository' in line and context.get('userRepository'):
                        context['userRepository'].delete_by_id(id_val)
                        result = {'success': True, 'message': 'Deleted successfully'}
                    elif 'productRepository' in line and context.get('productRepository'):
                        context['productRepository'].delete_by_id(id_val)
                        result = {'success': True, 'message': 'Deleted successfully'}
                    elif 'orderRepository' in line and context.get('orderRepository'):
                        context['orderRepository'].delete_by_id(id_val)
                        result = {'success': True, 'message': 'Deleted successfully'}
        
        print(f"[DEBUG] Final result: {result}")
        return result
    
    def initialize_http_server(self):
        """Initialize HTTP server with Flask"""
        if not self.enable_http_server:
            return
        
        try:
            from .http_server import NovaLangHTTPServer
            
            # Get server config
            if self.config:
                server_config = self.config.get_server_config()
                host = server_config.get('host', '0.0.0.0')
                port = server_config.get('port', 8080)
            else:
                host = '0.0.0.0'
                port = 8080
            
            self.http_server = NovaLangHTTPServer(host, port)
            
            # Configure CORS from config
            if self.config:
                cors_origins = self.config.get('cors.allowedOrigins', 
                    'http://localhost:3000,http://localhost:4200').split(',')
                cors_methods = self.config.get('cors.allowedMethods',
                    'GET,POST,PUT,DELETE,OPTIONS').split(',')
                self.http_server.configure_cors(cors_origins, cors_methods)
            
            return True
        except ImportError as e:
            print(f"⚠️  Flask not installed. Install with: pip install flask flask-cors")
            print(f"   HTTP server disabled")
            return False
    
    def start_server(self):
        """Start HTTP server with REST APIs"""
        if self.enable_http_server and self.http_server:
            # Register repositories, services, controllers
            for repo_name, repo_instance in self.repositories.items():
                self.http_server.register_repository(repo_name, repo_instance)
            
            print(f"🔧 Initialized {len(self.repositories)} repositories with CRUD operations")
            print(f"⚙️  Registered {len(self.services)} services with dependency injection")
            print(f"🌐 Registered {sum(len(c['routes']) for c in self.controllers.values())} REST endpoints")
            
            # Start the server
            self.http_server.start()
        else:
            # Fallback message
            if self.config:
                server_config = self.config.get_server_config()
                host = server_config['host']
                port = server_config['port']
                print(f"🌐 Server would start on http://{host}:{port}")
                print("   (HTTP server implementation coming soon)")
            else:
                print("🌐 Server would start on http://localhost:8080")
                print("   (HTTP server implementation coming soon)")
    
    def cleanup(self):
        """Cleanup resources"""
        if self.db_connection:
            self.db_connection.close()
            print("📦 Database connection closed")

def main():
    """Test the runtime"""
    runtime = NovaLangRuntime()
    
    test_code = """
    let x = 5
    let y = 10
    let sum = x + y
    print("Sum:", sum)
    
    function add(a, b) {
        return a + b
    }
    
    let result = add(20, 30)
    print("Result:", result)
    
    for (let i = 0; i < 3; i++) {
        print("Loop:", i)
    }
    """
    
    runtime.execute_code(test_code)
    runtime.cleanup()

if __name__ == "__main__":
    main()
