use boa_engine::{Context, JsValue};
use boa_engine::property::Attribute;
use serde::{Deserialize, Serialize};
use serde_json::Value;

#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct EvalResult {
    data: Option<Value>,
    error: Option<String>,
}

impl EvalResult {
    fn ok(data: JsValue) -> Self {
        match data {
            JsValue::Undefined => {
                return Self {
                    data: None,
                    error: None,
                };
            }
            _ => {}
        }
        let mut context = Context::default();
        match data.to_json(&mut context) {
            Err(e) => Self {
                data: None,
                error: Some(format!("{}", e)),
            },
            Ok(data_json) => Self {
                data: Some(data_json),
                error: None,
            }
        }
    }
    fn err(error: String) -> Self {
        Self {
            data: None,
            error: Some(error),
        }
    }
}

pub(crate) fn inner_eval(js: &str) -> EvalResult {
    let mut context = Context::default();
    context.set_trace(true);
    context.register_global_property("JS_ENGINE", "1.0.0", Attribute::all());
    // context.register_global_function("print", 0, print);

    match context.eval(js) {
        Ok(res) => EvalResult::ok(res),
        Err(e) => EvalResult::err(format!("{}", e)),
    }
}