from __future__ import annotations
import math
import random
from typing import TYPE_CHECKING, Optional, Tuple

if TYPE_CHECKING:
    from .interpreter import InterpreterState, StackEntry

from .interpreter_types import StackType
from .lexer import Token, TokenType, IntegerLiteral, IntegerBuiltInType, Identifier


# =====================================================================
#  Helper Functions
# =====================================================================

class NumericTypeFlags:
    """Flags to track numeric type properties"""
    FLOAT = 1 << 0
    SIGNED = 1 << 1
    BITS_64 = 1 << 2
    BITS_32 = 1 << 3
    BITS_16 = 1 << 4
    BITS_8 = 1 << 5


def extract_numeric_value(entry: "StackEntry") -> Optional[Tuple[float, int, int]]:
    """
    Extract numeric value from stack entry.
    Returns: (float_value, int_value, type_flags) or None if not numeric
    """
    flags = 0
    fval = 0.0
    ival = 0
    
    if entry.type == StackType.I64:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_64 | NumericTypeFlags.SIGNED
    elif entry.type == StackType.I32:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_32 | NumericTypeFlags.SIGNED
    elif entry.type == StackType.I16:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_16 | NumericTypeFlags.SIGNED
    elif entry.type == StackType.I8:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_8 | NumericTypeFlags.SIGNED
    elif entry.type == StackType.U64:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_64
    elif entry.type == StackType.U32:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_32
    elif entry.type == StackType.U16:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_16
    elif entry.type == StackType.U8:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_8
    elif entry.type == StackType.FLOAT:
        fval = float(entry.value) # type: ignore
        flags = NumericTypeFlags.BITS_32 | NumericTypeFlags.FLOAT
    elif entry.type == StackType.DOUBLE:
        fval = float(entry.value) # type: ignore
        flags = NumericTypeFlags.BITS_64 | NumericTypeFlags.FLOAT
    elif entry.type == StackType.CHARACTER:
        ival = int(entry.value) # type: ignore
        fval = float(ival)
        flags = NumericTypeFlags.BITS_8
    elif entry.type == StackType.BOOLEAN:
        ival = 1 if entry.value else 0
        fval = float(ival)
        flags = NumericTypeFlags.BITS_8
    else:
        return None
    
    return (fval, ival, flags)


def get_numeric_two(state: "InterpreterState") -> Optional[Tuple[float, float, int, int, int]]:
    """
    Extract two numeric values from top of stack.
    Returns: (fval_a, fval_b, ival_a, ival_b, combined_flags) or None
    """
    if len(state.stack) < 2:
        return None
    
    entry_a = state.stack[-1]
    entry_b = state.stack[-2]
    
    result_a = extract_numeric_value(entry_a)
    result_b = extract_numeric_value(entry_b)
    
    if result_a is None or result_b is None:
        return None
    
    fval_a, ival_a, flags_a = result_a
    fval_b, ival_b, flags_b = result_b
    
    # Combine flags (bitwise OR)
    combined_flags = flags_a | flags_b
    
    return (fval_a, fval_b, ival_a, ival_b, combined_flags)


def get_numeric_one(state: "InterpreterState") -> Optional[Tuple[float, int, int]]:
    """
    Extract one numeric value from top of stack.
    Returns: (fval, ival, flags) or None
    """
    if len(state.stack) < 1:
        return None
    
    entry = state.stack[-1]
    result = extract_numeric_value(entry)
    
    if result is None:
        return None
    
    return result


def create_numeric_token(flags: int, fval: float, ival: int) -> Token:
    """Create a token from numeric value based on type flags"""
    if flags & NumericTypeFlags.FLOAT:
        if flags & NumericTypeFlags.BITS_64:
            return Token(type=TokenType.DOUBLE, double_literal=fval)
        else:
            return Token(type=TokenType.FLOAT, float_literal=float(fval))
    else:
        # Integer type
        if flags & NumericTypeFlags.SIGNED:
            if flags & NumericTypeFlags.BITS_64:
                int_type = IntegerBuiltInType.I64
            elif flags & NumericTypeFlags.BITS_32:
                int_type = IntegerBuiltInType.I32
            elif flags & NumericTypeFlags.BITS_16:
                int_type = IntegerBuiltInType.I16
            else:
                int_type = IntegerBuiltInType.I8
        else:
            if flags & NumericTypeFlags.BITS_64:
                int_type = IntegerBuiltInType.U64
            elif flags & NumericTypeFlags.BITS_32:
                int_type = IntegerBuiltInType.U32
            elif flags & NumericTypeFlags.BITS_16:
                int_type = IntegerBuiltInType.U16
            else:
                int_type = IntegerBuiltInType.U8
        
        return Token(
            type=TokenType.INTEGER,
            integer_literal=IntegerLiteral(value=ival, type=int_type)
        )


def is_truthy(entry: "StackEntry") -> bool:
    """Check if a stack entry is truthy"""
    if entry.type == StackType.IDENTIFIER:
        return False
    elif entry.type in (StackType.I64, StackType.I32, StackType.I16, StackType.I8,
                        StackType.U64, StackType.U32, StackType.U16, StackType.U8):
        return bool(entry.value)
    elif entry.type in (StackType.FLOAT, StackType.DOUBLE):
        return bool(entry.value)
    elif entry.type == StackType.CHARACTER:
        return bool(entry.value)
    elif entry.type == StackType.BOOLEAN:
        return bool(entry.value)
    elif entry.type in (StackType.TOKEN_STRING, StackType.CALLABLE):
        ts = entry.value
        return len(ts.tokens) > 0 and ts.tokens[0].type != TokenType.EOF # type: ignore
    return False


def get_scalar_value(entry: "StackEntry") -> Optional[int]:
    """Extract a scalar (non-negative integer) value from stack entry"""
    if entry.type == StackType.I64:
        val = int(entry.value) # type: ignore
        if val < 0:
            return None
        return val
    elif entry.type == StackType.I32:
        val = int(entry.value) # type: ignore
        if val < 0:
            return None
        return val
    elif entry.type == StackType.I16:
        val = int(entry.value) # type: ignore
        if val < 0:
            return None
        return val
    elif entry.type == StackType.I8:
        val = int(entry.value) # type: ignore
        if val < 0:
            return None
        return val
    elif entry.type in (StackType.U64, StackType.U32, StackType.U16, StackType.U8):
        return int(entry.value) # type: ignore
    elif entry.type == StackType.CHARACTER:
        return int(entry.value) # type: ignore
    elif entry.type == StackType.BOOLEAN:
        return 1 if entry.value else 0
    else:
        return None


# =====================================================================
#  Arithmetic Operations
# =====================================================================

def builtin_addition(state: "InterpreterState") -> bool:
    """Add two numeric values"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, ival_a, ival_b, flags = result
    state.pop()
    state.pop()
    
    if flags & NumericTypeFlags.FLOAT:
        result_val = fval_b + fval_a
        token = create_numeric_token(flags, result_val, 0)
    else:
        result_val = ival_b + ival_a
        token = create_numeric_token(flags, 0.0, result_val)
    
    return state.push_token(token)


def builtin_subtraction(state: "InterpreterState") -> bool:
    """Subtract two numeric values"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, ival_a, ival_b, flags = result
    state.pop()
    state.pop()
    
    if flags & NumericTypeFlags.FLOAT:
        result_val = fval_b - fval_a
        token = create_numeric_token(flags, result_val, 0)
    else:
        result_val = ival_b - ival_a
        token = create_numeric_token(flags, 0.0, result_val)
    
    return state.push_token(token)


def builtin_multiplication(state: "InterpreterState") -> bool:
    """Multiply two numeric values"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, ival_a, ival_b, flags = result
    state.pop()
    state.pop()
    
    if flags & NumericTypeFlags.FLOAT:
        result_val = fval_b * fval_a
        token = create_numeric_token(flags, result_val, 0)
    else:
        result_val = ival_b * ival_a
        token = create_numeric_token(flags, 0.0, result_val)
    
    return state.push_token(token)


def builtin_division(state: "InterpreterState") -> bool:
    """Divide two numeric values (always returns float)"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    
    if fval_a == 0:
        return False
    
    state.pop()
    state.pop()
    
    result_val = fval_b / fval_a
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=result_val))


def builtin_modulus(state: "InterpreterState") -> bool:
    """Modulo operation (integers only)"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    _, _, ival_a, ival_b, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    if ival_a == 0:
        return False
    
    state.pop()
    state.pop()
    
    result_val = ival_b % ival_a
    token = create_numeric_token(flags, 0.0, result_val)
    return state.push_token(token)


def builtin_exponential(state: "InterpreterState") -> bool:
    """Exponentiation (always returns float)"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    result_val = math.pow(fval_b, fval_a)
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=result_val))


# =====================================================================
#  Comparison Operations
# =====================================================================

def builtin_greater_than(state: "InterpreterState") -> bool:
    """Greater than comparison"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=fval_b > fval_a))


def builtin_greater_than_or_equal_to(state: "InterpreterState") -> bool:
    """Greater than or equal comparison"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=fval_b >= fval_a))


def builtin_less_than(state: "InterpreterState") -> bool:
    """Less than comparison"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=fval_b < fval_a))


def builtin_less_than_or_equal_to(state: "InterpreterState") -> bool:
    """Less than or equal comparison"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=fval_b <= fval_a))


def builtin_equal_to(state: "InterpreterState") -> bool:
    """Equality comparison"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=fval_b == fval_a))


def builtin_not_equal_to(state: "InterpreterState") -> bool:
    """Inequality comparison"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=fval_b != fval_a))


# =====================================================================
#  Mathematical Functions
# =====================================================================

def builtin_abs(state: "InterpreterState") -> bool:
    """Absolute value"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, ival, flags = result
    
    # Only works on signed types or floats
    if not ((flags & NumericTypeFlags.SIGNED) or (flags & NumericTypeFlags.FLOAT)):
        return False
    
    state.pop()
    
    if flags & NumericTypeFlags.FLOAT:
        result_val = abs(fval)
        token = create_numeric_token(flags, result_val, 0)
    else:
        result_val = abs(ival)
        token = create_numeric_token(flags, 0.0, result_val)
    
    return state.push_token(token)


def builtin_sqrt(state: "InterpreterState") -> bool:
    """Square root"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    
    if fval < 0:
        return False
    
    state.pop()
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.sqrt(fval)))


def builtin_sin(state: "InterpreterState") -> bool:
    """Sine function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.sin(fval)))


def builtin_cos(state: "InterpreterState") -> bool:
    """Cosine function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.cos(fval)))


def builtin_tan(state: "InterpreterState") -> bool:
    """Tangent function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.tan(fval)))


def builtin_asin(state: "InterpreterState") -> bool:
    """Arc sine function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    
    if fval < -1 or fval > 1:
        return False
    
    state.pop()
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.asin(fval)))


def builtin_acos(state: "InterpreterState") -> bool:
    """Arc cosine function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    
    if fval < -1 or fval > 1:
        return False
    
    state.pop()
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.acos(fval)))


def builtin_atan(state: "InterpreterState") -> bool:
    """Arc tangent function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.atan(fval)))


def builtin_atan2(state: "InterpreterState") -> bool:
    """Two-argument arc tangent function"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, _, _, _ = result
    state.pop()
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.atan2(fval_b, fval_a)))


def builtin_floor(state: "InterpreterState") -> bool:
    """Floor function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.floor(fval)))


def builtin_ceil(state: "InterpreterState") -> bool:
    """Ceiling function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.ceil(fval)))


def builtin_round(state: "InterpreterState") -> bool:
    """Round function"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    state.pop()
    
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=round(fval)))


def builtin_ln(state: "InterpreterState") -> bool:
    """Natural logarithm"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    
    if fval <= 0:
        return False
    
    state.pop()
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.log(fval)))


def builtin_log(state: "InterpreterState") -> bool:
    """Base-10 logarithm"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, _, _ = result
    
    if fval <= 0:
        return False
    
    state.pop()
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=math.log10(fval)))


# =====================================================================
#  Logical Operations
# =====================================================================

def builtin_and(state: "InterpreterState") -> bool:
    """Logical AND"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, ival_a, ival_b, flags = result
    state.pop()
    state.pop()
    
    if flags & NumericTypeFlags.FLOAT:
        result_val = bool(fval_b and fval_a)
    else:
        result_val = bool(ival_b and ival_a)
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=result_val))


def builtin_or(state: "InterpreterState") -> bool:
    """Logical OR"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    fval_a, fval_b, ival_a, ival_b, flags = result
    state.pop()
    state.pop()
    
    if flags & NumericTypeFlags.FLOAT:
        result_val = bool(fval_b or fval_a)
    else:
        result_val = bool(ival_b or ival_a)
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=result_val))


def builtin_not(state: "InterpreterState") -> bool:
    """Logical NOT"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    fval, ival, flags = result
    state.pop()
    
    if flags & NumericTypeFlags.FLOAT:
        result_val = not bool(fval)
    else:
        result_val = not bool(ival)
    
    return state.push_token(Token(type=TokenType.BOOLEAN, boolean_literal=result_val))


# =====================================================================
#  Bitwise Operations
# =====================================================================

def builtin_bitand(state: "InterpreterState") -> bool:
    """Bitwise AND"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    _, _, ival_a, ival_b, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    state.pop()
    state.pop()
    
    result_val = ival_b & ival_a
    token = create_numeric_token(flags, 0.0, result_val)
    return state.push_token(token)


def builtin_bitor(state: "InterpreterState") -> bool:
    """Bitwise OR"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    _, _, ival_a, ival_b, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    state.pop()
    state.pop()
    
    result_val = ival_b | ival_a
    token = create_numeric_token(flags, 0.0, result_val)
    return state.push_token(token)


def builtin_bitxor(state: "InterpreterState") -> bool:
    """Bitwise XOR"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    _, _, ival_a, ival_b, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    state.pop()
    state.pop()
    
    result_val = ival_b ^ ival_a
    token = create_numeric_token(flags, 0.0, result_val)
    return state.push_token(token)


def builtin_bitnot(state: "InterpreterState") -> bool:
    """Bitwise NOT"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    _, ival, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    state.pop()
    
    result_val = ~ival
    token = create_numeric_token(flags, 0.0, result_val)
    return state.push_token(token)


def builtin_shl(state: "InterpreterState") -> bool:
    """Bitwise left shift"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    _, _, ival_a, ival_b, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    state.pop()
    state.pop()
    
    result_val = ival_b << ival_a
    token = create_numeric_token(flags, 0.0, result_val)
    return state.push_token(token)


def builtin_shr(state: "InterpreterState") -> bool:
    """Bitwise right shift"""
    result = get_numeric_two(state)
    if result is None:
        return False
    
    _, _, ival_a, ival_b, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    state.pop()
    state.pop()
    
    result_val = ival_b >> ival_a
    token = create_numeric_token(flags, 0.0, result_val)
    return state.push_token(token)


# =====================================================================
#  Stack Operations
# =====================================================================

def builtin_dup(state: "InterpreterState") -> bool:
    """Duplicate top stack item"""
    if len(state.stack) < 1:
        return False
    
    top = state.stack[-1]
    
    # Deep copy for token strings
    if top.type in (StackType.TOKEN_STRING, StackType.CALLABLE):
        value_copy = top.value.deep_copy() # type: ignore
    else:
        value_copy = top.value
    
    from .interpreter import StackEntry
    state.push(StackEntry(type=top.type, value=value_copy))
    return True


def builtin_drop(state: "InterpreterState") -> bool:
    """Drop top stack item"""
    if len(state.stack) < 1:
        return False
    
    state.pop()
    return True


def builtin_swap(state: "InterpreterState") -> bool:
    """Swap top two stack items"""
    if len(state.stack) < 2:
        return False
    
    a = state.pop()
    b = state.pop()
    state.push(a) # type: ignore
    state.push(b) # type: ignore
    return True


def builtin_depth(state: "InterpreterState") -> bool:
    """Push stack depth"""
    depth = len(state.stack)
    return state.push_token(Token(
        type=TokenType.INTEGER,
        integer_literal=IntegerLiteral(value=depth, type=IntegerBuiltInType.U64)
    ))


def builtin_pick(state: "InterpreterState") -> bool:
    """Copy nth item to top (0 = top)"""
    if len(state.stack) < 1:
        return False
    
    result = get_numeric_one(state)
    if result is None:
        return False
    
    _, ival, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    n = int(ival)
    
    if n < 0 or n >= len(state.stack) - 1:
        return False
    
    state.pop()  # Remove the index
    
    # Pick from stack (0 = current top, 1 = one below, etc.)
    picked_idx = len(state.stack) - 1 - n
    if picked_idx < 0:
        return False
    
    picked = state.stack[picked_idx]
    
    # Deep copy for token strings
    if picked.type in (StackType.TOKEN_STRING, StackType.CALLABLE):
        value_copy = picked.value.deep_copy() # type: ignore
    else:
        value_copy = picked.value
    
    from .interpreter import StackEntry
    state.push(StackEntry(type=picked.type, value=value_copy))
    return True


def builtin_roll(state: "InterpreterState") -> bool:
    """Rotate top n items, times times"""
    if len(state.stack) < 2:
        return False
    
    times_entry = state.stack[-1]
    count_entry = state.stack[-2]
    
    times_val = get_scalar_value(times_entry)
    count_val = get_scalar_value(count_entry)
    
    if times_val is None or count_val is None:
        return False
    
    if count_val <= 0:
        state.pop()
        state.pop()
        return True
    
    if count_val > len(state.stack) - 2:
        return False
    
    state.pop()
    state.pop()
    
    # Extract the top count_val items
    items = []
    for _ in range(count_val):
        if len(state.stack) < 1:
            return False
        items.append(state.pop())
    
    items.reverse()  # Reverse to get proper order
    
    # Rotate items by times_val
    times_val = times_val % len(items) if len(items) > 0 else 0
    rotated = items[times_val:] + items[:times_val]
    
    # Push back in reverse order
    for item in reversed(rotated):
        state.push(item)
    
    return True


# =====================================================================
#  Control Flow Operations
# =====================================================================

def builtin_if(state: "InterpreterState") -> bool:
    """Conditional execution: condition then_block else_block if"""
    if len(state.stack) < 3:
        return False
    
    else_block = state.pop()
    then_block = state.pop()
    condition = state.pop()
    
    # Check that blocks are executable
    if else_block.type not in (StackType.TOKEN_STRING, StackType.CALLABLE, StackType.IDENTIFIER): # type: ignore
        return False
    if then_block.type not in (StackType.TOKEN_STRING, StackType.CALLABLE, StackType.IDENTIFIER): # type: ignore
        return False
    
    # Evaluate condition
    is_true = is_truthy(condition) # type: ignore
    
    # Execute appropriate block
    if is_true:
        block_to_execute = then_block
    else:
        block_to_execute = else_block
    
    if block_to_execute.type == StackType.IDENTIFIER: # type: ignore
        return state.execute_func(block_to_execute.value.name) # type: ignore
    else:
        return state.execute_token_string(block_to_execute.value) # type: ignore


def builtin_while(state: "InterpreterState") -> bool:
    """While loop: condition_block body_block while"""
    if len(state.stack) < 2:
        return False
    
    body_block = state.pop()
    condition_block = state.pop()
    
    # Check that blocks are executable
    if body_block.type not in (StackType.TOKEN_STRING, StackType.CALLABLE, StackType.IDENTIFIER): # type: ignore
        return False
    if condition_block.type not in (StackType.TOKEN_STRING, StackType.CALLABLE, StackType.IDENTIFIER): # type: ignore
        return False
    
    while True:
        # Execute condition block
        if condition_block.type == StackType.IDENTIFIER: # type: ignore
            if not state.execute_func(condition_block.value.name): # type: ignore
                return False
        else:
            if not state.execute_token_string(condition_block.value): # type: ignore
                return False
        
        # Check result
        if len(state.stack) < 1:
            return False
        
        condition_result = state.pop()
        if not is_truthy(condition_result): # type: ignore
            break
        
        # Execute body block
        if body_block.type == StackType.IDENTIFIER: # type: ignore
            if not state.execute_func(body_block.value.name): # type: ignore
                return False
        else:
            if not state.execute_token_string(body_block.value): # type: ignore
                return False
    
    return True


def builtin_for(state: "InterpreterState") -> bool:
    """For loop: start end body_block for"""
    if len(state.stack) < 3:
        return False
    
    body_block = state.pop()
    end_item = state.pop()
    start_item = state.pop()
    
    # Check that block is executable
    if body_block.type not in (StackType.TOKEN_STRING, StackType.CALLABLE, StackType.IDENTIFIER): # type: ignore
        return False
    
    start_val = get_scalar_value(start_item) # type: ignore
    end_val = get_scalar_value(end_item) # type: ignore
    
    if start_val is None or end_val is None:
        return False
    
    # Execute loop
    for i in range(start_val, end_val):
        # Push counter
        if not state.push_token(Token(
            type=TokenType.INTEGER,
            integer_literal=IntegerLiteral(value=i, type=IntegerBuiltInType.I64)
        )):
            return False
        
        # Execute body
        if body_block.type == StackType.IDENTIFIER: # type: ignore
            if not state.execute_func(body_block.value.name): # type: ignore
                return False
        else:
            if not state.execute_token_string(body_block.value): # type: ignore
                return False
    
    return True


# =====================================================================
#  Special Operations
# =====================================================================

def builtin_eval(state: "InterpreterState") -> bool:
    """Evaluate code block or identifier"""
    if len(state.stack) < 1:
        return False
    
    code_target = state.pop()
    
    if code_target.type in (StackType.TOKEN_STRING, StackType.CALLABLE): # type: ignore
        return state.execute_token_string(code_target.value) # type: ignore
    elif code_target.type == StackType.IDENTIFIER: # type: ignore
        return state.execute_func(code_target.value.name) # type: ignore
    else:
        return False


def builtin_lambda(state: "InterpreterState") -> bool:
    """Convert token string to callable"""
    if len(state.stack) < 1:
        return False
    
    if state.stack[-1].type != StackType.TOKEN_STRING:
        return False
    
    state.stack[-1].type = StackType.CALLABLE
    return True


def builtin_const(state: "InterpreterState") -> bool:
    """Define a constant: value ::name const"""
    if len(state.stack) < 2:
        return False
    
    name_entry = state.pop()
    value_entry = state.pop()
    
    if name_entry.type != StackType.IDENTIFIER: # type: ignore
        return False
    
    if value_entry.type != StackType.CALLABLE: # type: ignore
        return False
    
    name = name_entry.value.name # type: ignore
    
    # Check if function already exists
    if state.get_function(name) is not None:
        return False
    
    # Create function item
    state.add_function(name, value_entry.value) # type: ignore
    
    return True


def builtin_type_of(state: "InterpreterState") -> bool:
    """Get the type of the top stack item"""
    if len(state.stack) < 1:
        return False
    
    item = state.pop()
    
    # Map stack type to type name
    type_names = {
        StackType.IDENTIFIER: "Identifier",
        StackType.I64: "i64",
        StackType.I32: "i32",
        StackType.I16: "i16",
        StackType.I8: "i8",
        StackType.U64: "u64",
        StackType.U32: "u32",
        StackType.U16: "u16",
        StackType.U8: "u8",
        StackType.FLOAT: "f32",
        StackType.DOUBLE: "f64",
        StackType.CHARACTER: "char",
        StackType.BOOLEAN: "bool",
        StackType.TOKEN_STRING: "TokenString",
        StackType.CALLABLE: "Callable",
    }
    
    type_name = type_names.get(item.type, "Unknown") # type: ignore
    
    return state.push_token(Token(
        type=TokenType.IDENTIFIER,
        identifier=Identifier(name=type_name, is_literal=True)
    ))


# =====================================================================
#  Random Number Operations
# =====================================================================

def builtin_rand(state: "InterpreterState") -> bool:
    """Generate random number [0.0, 1.0)"""
    return state.push_token(Token(type=TokenType.DOUBLE, double_literal=random.random()))


def builtin_seed(state: "InterpreterState") -> bool:
    """Seed random number generator"""
    result = get_numeric_one(state)
    if result is None:
        return False
    
    _, ival, flags = result
    
    if flags & NumericTypeFlags.FLOAT:
        return False
    
    state.pop()
    random.seed(ival)
    return True


# =====================================================================
#  Load Builtins
# =====================================================================

def load_builtins(interpreter_state: "InterpreterState") -> bool:
    """Load all builtin functions into the interpreter state"""
    
    builtins = {
        # Arithmetic
        "+": builtin_addition,
        "-": builtin_subtraction,
        "*": builtin_multiplication,
        "/": builtin_division,
        "%": builtin_modulus,
        "^": builtin_exponential,
        
        # Comparison
        ">": builtin_greater_than,
        ">=": builtin_greater_than_or_equal_to,
        "<": builtin_less_than,
        "<=": builtin_less_than_or_equal_to,
        "==": builtin_equal_to,
        "!=": builtin_not_equal_to,
        
        # Mathematical functions
        "abs": builtin_abs,
        "sqrt": builtin_sqrt,
        "sin": builtin_sin,
        "cos": builtin_cos,
        "tan": builtin_tan,
        "asin": builtin_asin,
        "acos": builtin_acos,
        "atan": builtin_atan,
        "atan2": builtin_atan2,
        "floor": builtin_floor,
        "ceil": builtin_ceil,
        "round": builtin_round,
        "ln": builtin_ln,
        "log": builtin_log,
        
        # Logical
        "and": builtin_and,
        "or": builtin_or,
        "not": builtin_not,
        
        # Bitwise
        "bitand": builtin_bitand,
        "bitor": builtin_bitor,
        "bitxor": builtin_bitxor,
        "bitnot": builtin_bitnot,
        "shl": builtin_shl,
        "shr": builtin_shr,
        
        # Stack operations
        "dup": builtin_dup,
        "drop": builtin_drop,
        "swap": builtin_swap,
        "depth": builtin_depth,
        "pick": builtin_pick,
        "roll": builtin_roll,
        
        # Control flow
        "if": builtin_if,
        "while": builtin_while,
        "for": builtin_for,
        
        # Special
        "eval": builtin_eval,
        "lambda": builtin_lambda,
        "const": builtin_const,
        "type_of": builtin_type_of,
        
        # Random
        "rand": builtin_rand,
        "seed": builtin_seed,
    }
    
    # Register all builtins
    for name, func in builtins.items():
        interpreter_state.add_function(name, func)
    
    # Load SLS-defined builtins
    try:
        from .lexer import LexerInfo, lexical_analysis
        
        builtin_code = """
// Kyler Olsen
// YREA SLS
// SLS Defined Builtin Operators
// November 2025

{ ln swap ln swap / } lambda ::logb const
{ 1 pick 1 pick < { swap drop } { drop } if } lambda ::max const
{ 1 pick 1 pick < { drop } { swap drop } if } lambda ::min const
{ 3 1 roll } lambda ::rot const
"""
        
        lexer_info = LexerInfo("__builtin.sls", builtin_code)
        tokens = lexical_analysis(lexer_info)
        
        for token in tokens:
            if token.type == TokenType.EOF:
                break
            if not interpreter_state.execute(token):
                return False
        
        return True
    
    except Exception as e:
        print(f"Failed to load builtin definitions: {e}")
        return False
