use crate::interpreter::{
    InterpreterState,
    StackValue,
    FunctionItem,
    BuiltinFunction,
    BuiltinFn,
};
use crate::lexer::{Token, Identifier};
use std::collections::HashMap;

// Numeric type flags
bitflags::bitflags! {
    #[derive(Debug, Clone, Copy)]
    struct NumericType: u32 {
        const FLOAT = 1 << 0;
        const SIGNED = 1 << 1;
        const BITS_64 = 1 << 2;
        const BITS_32 = 1 << 3;
        const BITS_16 = 1 << 4;
        const BITS_8 = 1 << 5;
    }
}

struct NumericValue {
    float_val: f64,
    int_val: u64,
    type_flags: NumericType,
}

// Extract numeric value from a single stack item
fn extract_numeric_type(item: &StackValue) -> Option<NumericValue> {
    let mut val = NumericValue {
        float_val: 0.0,
        int_val: 0,
        type_flags: NumericType::empty(),
    };

    match item {
        StackValue::I64(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_64 | NumericType::SIGNED;
        }
        StackValue::I32(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_32 | NumericType::SIGNED;
        }
        StackValue::I16(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_16 | NumericType::SIGNED;
        }
        StackValue::I8(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_8 | NumericType::SIGNED;
        }
        StackValue::U64(v) => {
            val.int_val = *v;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_64;
        }
        StackValue::U32(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_32;
        }
        StackValue::U16(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_16;
        }
        StackValue::U8(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_8;
        }
        StackValue::F32(v) => {
            val.float_val = *v as f64;
            val.type_flags = NumericType::BITS_32 | NumericType::FLOAT;
        }
        StackValue::F64(v) => {
            val.float_val = *v;
            val.type_flags = NumericType::BITS_64 | NumericType::FLOAT;
        }
        StackValue::Character(v) => {
            val.int_val = *v as u64;
            val.float_val = *v as f64;
        }
        StackValue::Boolean(v) => {
            val.int_val = *v as u64;
            val.float_val = if *v { 1.0 } else { 0.0 };
        }
        _ => return None,
    }

    Some(val)
}

// Extract two numeric values from stack
fn extract_numeric_types(state: &InterpreterState) -> Option<(NumericValue, NumericValue, NumericType)> {
    if state.stack.len() < 2 {
        return None;
    }

    let a = extract_numeric_type(&state.stack[state.stack.len()-1])?;
    let b = extract_numeric_type(&state.stack[state.stack.len()-2])?;

    // Combine type flags
    let combined = a.type_flags | b.type_flags;

    Some((a, b, combined))
}

// Convert numeric result to appropriate token based on type flags
fn numeric_to_token(float_val: f64, int_val: u64, type_flags: NumericType) -> Token {
    if type_flags.contains(NumericType::FLOAT) {
        if type_flags.contains(NumericType::BITS_64) {
            Token::Double(float_val)
        } else {
            Token::Float(float_val as f32)
        }
    } else if type_flags.contains(NumericType::SIGNED) {
        if type_flags.contains(NumericType::BITS_64) {
            Token::I64(int_val as i64)
        } else if type_flags.contains(NumericType::BITS_32) {
            Token::I32(int_val as i32)
        } else if type_flags.contains(NumericType::BITS_16) {
            Token::I16(int_val as i16)
        } else {
            Token::I8(int_val as i8)
        }
    } else {
        if type_flags.contains(NumericType::BITS_64) {
            Token::U64(int_val)
        } else if type_flags.contains(NumericType::BITS_32) {
            Token::U32(int_val as u32)
        } else if type_flags.contains(NumericType::BITS_16) {
            Token::U16(int_val as u16)
        } else {
            Token::U8(int_val as u8)
        }
    }
}

// Check if value is truthy
fn is_truthy(item: &StackValue) -> bool {
    match item {
        StackValue::I64(v) => *v != 0,
        StackValue::I32(v) => *v != 0,
        StackValue::I16(v) => *v != 0,
        StackValue::I8(v) => *v != 0,
        StackValue::U64(v) => *v != 0,
        StackValue::U32(v) => *v != 0,
        StackValue::U16(v) => *v != 0,
        StackValue::U8(v) => *v != 0,
        StackValue::F32(v) => *v != 0.0,
        StackValue::F64(v) => *v != 0.0,
        StackValue::Character(v) => *v != 0,
        StackValue::Boolean(v) => *v,
        StackValue::TokenString(ts)  => {
            !ts.tokens.is_empty() && !matches!(ts.tokens[0], Token::Eof)
        }
        StackValue::Callable(_) => false,
        _ => false,
    }
}

// Extract scalar value (for indexing operations)
fn extract_scalar(item: &StackValue) -> Option<usize> {
    match item {
        StackValue::I64(v) if *v >= 0 => Some(*v as usize),
        StackValue::I32(v) if *v >= 0 => Some(*v as usize),
        StackValue::I16(v) if *v >= 0 => Some(*v as usize),
        StackValue::I8(v) if *v >= 0 => Some(*v as usize),
        StackValue::U64(v) => Some(*v as usize),
        StackValue::U32(v) => Some(*v as usize),
        StackValue::U16(v) => Some(*v as usize),
        StackValue::U8(v) => Some(*v as usize),
        StackValue::Character(v) => Some(*v as usize),
        StackValue::Boolean(v) => Some(*v as usize),
        _ => None,
    }
}

// Builtin function implementations

pub fn builtin_addition(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();

    let result = if type_flags.contains(NumericType::FLOAT) {
        numeric_to_token(b.float_val + a.float_val, 0, type_flags)
    } else {
        numeric_to_token(0.0, b.int_val.wrapping_add(a.int_val), type_flags)
    };

    state.push_token(&result);
    true
}

pub fn builtin_subtraction(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();

    let result = if type_flags.contains(NumericType::FLOAT) {
        numeric_to_token(b.float_val - a.float_val, 0, type_flags)
    } else {
        numeric_to_token(0.0, b.int_val.wrapping_sub(a.int_val), type_flags)
    };

    state.push_token(&result);
    true
}

pub fn builtin_multiplication(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();

    let result = if type_flags.contains(NumericType::FLOAT) {
        numeric_to_token(b.float_val * a.float_val, 0, type_flags)
    } else {
        numeric_to_token(0.0, b.int_val.wrapping_mul(a.int_val), type_flags)
    };

    state.push_token(&result);
    true
}

pub fn builtin_division(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    if a.float_val == 0.0 {
        return false;
    }

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::F64(b.float_val / a.float_val));
    true
}

pub fn builtin_modulus(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    if type_flags.contains(NumericType::FLOAT) || a.int_val == 0 {
        return false;
    }

    state.stack.pop();
    state.stack.pop();

    let result = numeric_to_token(0.0, b.int_val % a.int_val, type_flags);
    state.push_token(&result);
    true
}

pub fn builtin_exponential(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::F64(b.float_val.powf(a.float_val)));
    true
}

pub fn builtin_greater_than(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::Boolean(b.float_val > a.float_val));
    true
}

pub fn builtin_greater_than_or_equal_to(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::Boolean(b.float_val >= a.float_val));
    true
}

pub fn builtin_less_than(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::Boolean(b.float_val < a.float_val));
    true
}

pub fn builtin_less_than_or_equal_to(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::Boolean(b.float_val <= a.float_val));
    true
}

pub fn builtin_equal_to(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::Boolean(b.float_val == a.float_val));
    true
}

pub fn builtin_not_equal_to(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::Boolean(b.float_val != a.float_val));
    true
}

pub fn builtin_abs(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if !val.type_flags.contains(NumericType::SIGNED | NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();

    let result = if val.type_flags.contains(NumericType::FLOAT) {
        numeric_to_token(val.float_val.abs(), 0, val.type_flags)
    } else {
        numeric_to_token(0.0, (val.int_val as i64).unsigned_abs(), val.type_flags)
    };

    state.push_token(&result);
    true
}

pub fn builtin_acos(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if val.float_val < -1.0 || val.float_val > 1.0 {
        return false;
    }

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.acos()));
    true
}

pub fn builtin_and(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();

    let result = if type_flags.contains(NumericType::FLOAT) {
        b.float_val != 0.0 && a.float_val != 0.0
    } else {
        b.int_val != 0 && a.int_val != 0
    };

    state.stack.push(StackValue::Boolean(result));
    true
}

pub fn builtin_asin(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if val.float_val < -1.0 || val.float_val > 1.0 {
        return false;
    }

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.asin()));
    true
}

pub fn builtin_atan(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.atan()));
    true
}

pub fn builtin_atan2(state: &mut InterpreterState) -> bool {
    let Some((a, b, _)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.push(StackValue::F64(b.float_val.atan2(a.float_val)));
    true
}

// Bitwise operations
pub fn builtin_bitand(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    if type_flags.contains(NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();
    state.stack.pop();
    let result = numeric_to_token(0.0, b.int_val & a.int_val, type_flags);
    state.push_token(&result);
    true
}

pub fn builtin_bitnot(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if val.type_flags.contains(NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();
    let result = numeric_to_token(0.0, !val.int_val, val.type_flags);
    state.push_token(&result);
    true
}

pub fn builtin_bitor(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    if type_flags.contains(NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();
    state.stack.pop();
    let result = numeric_to_token(0.0, b.int_val | a.int_val, type_flags);
    state.push_token(&result);
    true
}

pub fn builtin_bitxor(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    if type_flags.contains(NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();
    state.stack.pop();
    let result = numeric_to_token(0.0, b.int_val ^ a.int_val, type_flags);
    state.push_token(&result);
    true
}

// Math functions
pub fn builtin_ceil(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.ceil()));
    true
}

pub fn builtin_floor(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.floor()));
    true
}

pub fn builtin_round(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.round()));
    true
}

pub fn builtin_sqrt(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if val.float_val < 0.0 {
        return false;
    }

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.sqrt()));
    true
}

pub fn builtin_sin(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.sin()));
    true
}

pub fn builtin_cos(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.cos()));
    true
}

pub fn builtin_tan(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.tan()));
    true
}

pub fn builtin_ln(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if val.float_val <= 0.0 {
        return false;
    }

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.ln()));
    true
}

pub fn builtin_log(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if val.float_val <= 0.0 {
        return false;
    }

    state.stack.pop();
    state.stack.push(StackValue::F64(val.float_val.log10()));
    true
}

// Stack operations
pub fn builtin_depth(state: &mut InterpreterState) -> bool {
    state.stack.push(StackValue::U64(state.stack.len() as u64));
    true
}

pub fn builtin_drop(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }
    state.stack.pop();
    true
}

pub fn builtin_dup(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }
    let item = state.stack[state.stack.len()-1].clone();
    state.stack.push(item);
    true
}

pub fn builtin_swap(state: &mut InterpreterState) -> bool {
    if state.stack.len() < 2 {
        return false;
    }
    state.stack.swap(0, 1);
    true
}

pub fn builtin_pick(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(index) = extract_scalar(&state.stack[state.stack.len()-1]) else {
        return false;
    };

    if index + 1 >= state.stack.len() {
        return false;
    }

    let item = state.stack[index + 1].clone();
    state.stack.pop();
    state.stack.push(item);
    true
}

pub fn builtin_roll(state: &mut InterpreterState) -> bool {
    if state.stack.len() < 2 {
        return false;
    }

    let Some(times) = extract_scalar(&state.stack[state.stack.len()-1]) else {
        return false;
    };

    let Some(count) = extract_scalar(&state.stack[state.stack.len()-2]) else {
        return false;
    };

    if count == 0 || count + 2 > state.stack.len() {
        return false;
    }

    state.stack.pop();
    state.stack.pop();

    // Rotate the top 'count' items 'times' times
    for _ in 0..times {
        let item = state.stack.remove(count - 1);
        state.stack.push(item);
    }

    true
}

// Logical operations
pub fn builtin_not(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let truthy = is_truthy(&state.stack[state.stack.len()-1]);
    state.stack.pop();
    state.stack.push(StackValue::Boolean(!truthy));
    true
}

pub fn builtin_or(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();

    let result = if type_flags.contains(NumericType::FLOAT) {
        b.float_val != 0.0 || a.float_val != 0.0
    } else {
        b.int_val != 0 || a.int_val != 0
    };

    state.stack.push(StackValue::Boolean(result));
    true
}

// Shift operations
pub fn builtin_shl(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    if type_flags.contains(NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();
    state.stack.pop();
    let result = numeric_to_token(0.0, b.int_val << a.int_val, type_flags);
    state.push_token(&result);
    true
}

pub fn builtin_shr(state: &mut InterpreterState) -> bool {
    let Some((a, b, type_flags)) = extract_numeric_types(state) else {
        return false;
    };

    if type_flags.contains(NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();
    state.stack.pop();
    let result = numeric_to_token(0.0, b.int_val >> a.int_val, type_flags);
    state.push_token(&result);
    true
}

// Random operations
pub fn builtin_rand(state: &mut InterpreterState) -> bool {
    use rand::Rng;
    let val = rand::thread_rng().gen::<f64>();
    state.stack.push(StackValue::F64(val));
    true
}

pub fn builtin_seed(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let Some(last) = state.stack.last() else { return false };
    let Some(val) = extract_numeric_type(last) else { return false };

    if val.type_flags.contains(NumericType::FLOAT) {
        return false;
    }

    state.stack.pop();
    // Note: Rust's rand crate doesn't have global seeding
    // You'd need to store the RNG in InterpreterState
    true
}

// Control flow operations
pub fn builtin_if(state: &mut InterpreterState) -> bool {
    if state.stack.len() < 3 {
        return false;
    }

    let else_block = match &state.stack[state.stack.len()-1] {
        StackValue::TokenString(ts) | StackValue::Callable(ts) => ts.clone(),
        _ => return false,
    };

    let then_block = match &state.stack[state.stack.len()-2] {
        StackValue::TokenString(ts) | StackValue::Callable(ts) => ts.clone(),
        _ => return false,
    };

    let condition = is_truthy(&state.stack[state.stack.len()-3]);

    state.stack.pop();
    state.stack.pop();
    state.stack.pop();

    if condition {
        state.execute_token_string(&then_block)
    } else {
        state.execute_token_string(&else_block)
    }
}

pub fn builtin_while(state: &mut InterpreterState) -> bool {
    if state.stack.len() < 2 {
        return false;
    }

    let while_block = match &state.stack[state.stack.len()-1] {
        StackValue::TokenString(ts) | StackValue::Callable(ts) => ts.clone(),
        _ => return false,
    };

    let cond_block = match &state.stack[state.stack.len()-2] {
        StackValue::TokenString(ts) | StackValue::Callable(ts) => ts.clone(),
        _ => return false,
    };

    state.stack.pop();
    state.stack.pop();

    loop {
        if !state.execute_token_string(&cond_block) {
            return false;
        }

        if state.stack.is_empty() {
            return false;
        }

        let condition = is_truthy(&state.stack[state.stack.len()-1]);
        state.stack.pop();

        if !condition {
            break;
        }

        if !state.execute_token_string(&while_block) {
            return false;
        }
    }

    true
}

pub fn builtin_for(state: &mut InterpreterState) -> bool {
    if state.stack.len() < 3 {
        return false;
    }

    let for_block = match &state.stack[state.stack.len()-1] {
        StackValue::TokenString(ts) | StackValue::Callable(ts) => ts.clone(),
        _ => return false,
    };

    let Some(end) = extract_scalar(&state.stack[state.stack.len()-2]) else {
        return false;
    };

    let Some(start) = extract_scalar(&state.stack[state.stack.len()-3]) else {
        return false;
    };

    state.stack.pop();
    state.stack.pop();
    state.stack.pop();

    for i in start..end {
        state.stack.push(StackValue::I64(i as i64));
        
        if !state.execute_token_string(&for_block) {
            return false;
        }
    }

    true
}

pub fn builtin_lambda(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }
    let stack_len = state.stack.len();

    match &mut state.stack[stack_len-1] {
        StackValue::TokenString(ts) => {
            let callable = StackValue::Callable(ts.clone());
            state.stack[stack_len-1] = callable;
            true
        }
        _ => false,
    }
}

pub fn builtin_eval(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let code = state.stack.pop();

    match code {
        Some(StackValue::TokenString(ts)) | Some(StackValue::Callable(ts)) => {
            state.execute_token_string(&ts)
        }
        Some(StackValue::Identifier(id)) => {
            state.execute_func(&id.name)
        }
        _ => false,
    }
}

pub fn builtin_const(state: &mut InterpreterState) -> bool {
    if state.stack.len() < 2 {
        return false;
    }

    let name = match &state.stack[state.stack.len()-1] {
        StackValue::Identifier(id) => id.name.clone(),
        _ => return false,
    };

    let value = match &state.stack[state.stack.len()-2] {
        StackValue::Callable(ts) => ts.clone(),
        _ => return false,
    };

    if state.functions.contains_key(&name) {
        return false;
    }

    state.stack.pop();
    state.stack.pop();
    
    state.functions.insert(name, FunctionItem::TokenString(value));

    true
}

pub fn builtin_type_of(state: &mut InterpreterState) -> bool {
    if state.stack.is_empty() {
        return false;
    }

    let type_name = match &state.stack[state.stack.len()-1] {
        StackValue::Identifier(_) => "Identifier",
        StackValue::I64(_) => "i64",
        StackValue::I32(_) => "i32",
        StackValue::I16(_) => "i16",
        StackValue::I8(_) => "i8",
        StackValue::U64(_) => "u64",
        StackValue::U32(_) => "u32",
        StackValue::U16(_) => "u16",
        StackValue::U8(_) => "u8",
        StackValue::F32(_) => "f32",
        StackValue::F64(_) => "f64",
        StackValue::Character(_) => "char",
        StackValue::Boolean(_) => "bool",
        StackValue::TokenString(_) => "TokenString",
        StackValue::Callable(_) => "Callable",
    };

    state.stack.pop();
    state.stack.push(StackValue::Identifier(Identifier {
        name: type_name.to_string(),
        is_literal: true,
    }));

    true
}

pub fn lookup_builtin(name: &str) -> Option<BuiltinFn> {
    if name == "+" { Some(builtin_addition) }
    else if name == "-" { Some(builtin_subtraction) }
    else if name == "*" { Some(builtin_multiplication) }
    else if name == "/" { Some(builtin_division) }
    else if name == "%" { Some(builtin_modulus) }
    else if name == "^" { Some(builtin_exponential) }
    else if name == ">" { Some(builtin_greater_than) }
    else if name == ">=" { Some(builtin_greater_than_or_equal_to) }
    else if name == "<" { Some(builtin_less_than) }
    else if name == "<=" { Some(builtin_less_than_or_equal_to) }
    else if name == "==" { Some(builtin_equal_to) }
    else if name == "!=" { Some(builtin_not_equal_to) }
    else if name == "abs" { Some(builtin_abs) }
    else if name == "acos" { Some(builtin_acos) }
    else if name == "asin" { Some(builtin_asin) }
    else if name == "atan" { Some(builtin_atan) }
    else if name == "atan2" { Some(builtin_atan2) }
    else if name == "ceil" { Some(builtin_ceil) }
    else if name == "floor" { Some(builtin_floor) }
    else if name == "round" { Some(builtin_round) }
    else if name == "sqrt" { Some(builtin_sqrt) }
    else if name == "sin" { Some(builtin_sin) }
    else if name == "cos" { Some(builtin_cos) }
    else if name == "tan" { Some(builtin_tan) }
    else if name == "ln" { Some(builtin_ln) }
    else if name == "log" { Some(builtin_log) }
    else if name == "and" { Some(builtin_and) }
    else if name == "or" { Some(builtin_or) }
    else if name == "not" { Some(builtin_not) }
    else if name == "bitand" { Some(builtin_bitand) }
    else if name == "bitnot" { Some(builtin_bitnot) }
    else if name == "bitor" { Some(builtin_bitor) }
    else if name == "bitxor" { Some(builtin_bitxor) }
    else if name == "shl" { Some(builtin_shl) }
    else if name == "shr" { Some(builtin_shr) }
    else if name == "depth" { Some(builtin_depth) }
    else if name == "drop" { Some(builtin_drop) }
    else if name == "dup" { Some(builtin_dup) }
    else if name == "swap" { Some(builtin_swap) }
    else if name == "pick" { Some(builtin_pick) }
    else if name == "roll" { Some(builtin_roll) }
    else if name == "if" { Some(builtin_if) }
    else if name == "while" { Some(builtin_while) }
    else if name == "for" { Some(builtin_for) }
    else if name == "lambda" { Some(builtin_lambda) }
    else if name == "eval" { Some(builtin_eval) }
    else if name == "const" { Some(builtin_const) }
    else if name == "type_of" { Some(builtin_type_of) }
    else if name == "rand" { Some(builtin_rand) }
    else if name == "seed" { Some(builtin_seed) }
    else { None }
}

// Helper to add builtin to function table
fn register_builtin(
    functions: &mut HashMap<String, FunctionItem>,
    name: &str,
    func: fn(&mut InterpreterState) -> bool,
) {
    functions.insert(name.to_string(), FunctionItem::Builtin(BuiltinFunction {
        name: name.to_string(),
        function: match lookup_builtin(name) {
            Some(func) => func,
            None => panic!("Builtin Not Found!"),
        }
    }));
}

pub fn load_builtins(state: &mut InterpreterState) -> bool {
    // Arithmetic
    register_builtin(&mut state.functions, "+", builtin_addition);
    register_builtin(&mut state.functions, "-", builtin_subtraction);
    register_builtin(&mut state.functions, "*", builtin_multiplication);
    register_builtin(&mut state.functions, "/", builtin_division);
    register_builtin(&mut state.functions, "%", builtin_modulus);
    register_builtin(&mut state.functions, "^", builtin_exponential);

    // Comparison
    register_builtin(&mut state.functions, ">", builtin_greater_than);
    register_builtin(&mut state.functions, ">=", builtin_greater_than_or_equal_to);
    register_builtin(&mut state.functions, "<", builtin_less_than);
    register_builtin(&mut state.functions, "<=", builtin_less_than_or_equal_to);
    register_builtin(&mut state.functions, "==", builtin_equal_to);
    register_builtin(&mut state.functions, "!=", builtin_not_equal_to);

    // Math functions
    register_builtin(&mut state.functions, "abs", builtin_abs);
    register_builtin(&mut state.functions, "acos", builtin_acos);
    register_builtin(&mut state.functions, "asin", builtin_asin);
    register_builtin(&mut state.functions, "atan", builtin_atan);
    register_builtin(&mut state.functions, "atan2", builtin_atan2);
    register_builtin(&mut state.functions, "ceil", builtin_ceil);
    register_builtin(&mut state.functions, "floor", builtin_floor);
    register_builtin(&mut state.functions, "round", builtin_round);
    register_builtin(&mut state.functions, "sqrt", builtin_sqrt);
    register_builtin(&mut state.functions, "sin", builtin_sin);
    register_builtin(&mut state.functions, "cos", builtin_cos);
    register_builtin(&mut state.functions, "tan", builtin_tan);
    register_builtin(&mut state.functions, "ln", builtin_ln);
    register_builtin(&mut state.functions, "log", builtin_log);

    // Logical
    register_builtin(&mut state.functions, "and", builtin_and);
    register_builtin(&mut state.functions, "or", builtin_or);
    register_builtin(&mut state.functions, "not", builtin_not);

    // Bitwise
    register_builtin(&mut state.functions, "bitand", builtin_bitand);
    register_builtin(&mut state.functions, "bitnot", builtin_bitnot);
    register_builtin(&mut state.functions, "bitor", builtin_bitor);
    register_builtin(&mut state.functions, "bitxor", builtin_bitxor);
    register_builtin(&mut state.functions, "shl", builtin_shl);
    register_builtin(&mut state.functions, "shr", builtin_shr);

    // Stack operations
    register_builtin(&mut state.functions, "depth", builtin_depth);
    register_builtin(&mut state.functions, "drop", builtin_drop);
    register_builtin(&mut state.functions, "dup", builtin_dup);
    register_builtin(&mut state.functions, "swap", builtin_swap);
    register_builtin(&mut state.functions, "pick", builtin_pick);
    register_builtin(&mut state.functions, "roll", builtin_roll);

    // Control flow
    register_builtin(&mut state.functions, "if", builtin_if);
    register_builtin(&mut state.functions, "while", builtin_while);
    register_builtin(&mut state.functions, "for", builtin_for);
    register_builtin(&mut state.functions, "lambda", builtin_lambda);
    register_builtin(&mut state.functions, "eval", builtin_eval);
    register_builtin(&mut state.functions, "const", builtin_const);

    // Utility
    register_builtin(&mut state.functions, "type_of", builtin_type_of);
    register_builtin(&mut state.functions, "rand", builtin_rand);
    register_builtin(&mut state.functions, "seed", builtin_seed);

    // Load SLS-defined builtins
    let builtin_code = r#"
// 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
"#;

    use crate::lexer::{LexerInfo, lexical_analysis};

    let mut lexer = LexerInfo::new("__builtin.sls", builtin_code);
    
    match lexical_analysis(&mut lexer) {
        Ok(tokens) => {
            for token in tokens {
                if matches!(token, Token::Eof) {
                    break;
                }
                if !state.execute(&token) {
                    eprintln!("Error in __builtin.sls");
                    return false;
                }
            }
        }
        Err(e) => {
            dbg!(e);
            return false
        }
    }

    true
}
