use alloc::string::String;
use core::ffi::c_int;
use luaur_common::functions::format::format;
use luaur_vm::functions::lua_gettop::lua_gettop;
use luaur_vm::functions::lua_isstring::lua_isstring;
use luaur_vm::functions::lua_typename::lua_typename;
use luaur_vm::macros::lua_tostring::lua_tostring;

use crate::type_aliases::lua_state::lua_State;

pub fn check_result_for_error_deprecated(
    L: *mut lua_State,
    type_function_name: &str,
    lua_result: c_int,
) -> Option<String> {
    match lua_result {
        0 => None, // LUA_OK
        1 | 3 => Some(format(format_args!(
            "'{}' type function errored: unexpected yield or break",
            type_function_name
        ))), // LUA_YIELD, LUA_BREAK
        _ => {
            if unsafe { lua_gettop(L as *mut luaur_vm::records::lua_state::lua_State) } == 0 {
                Some(format(format_args!(
                    "'{}' type function errored unexpectedly",
                    type_function_name
                )))
            } else if unsafe { lua_isstring(L as *mut luaur_vm::records::lua_state::lua_State, -1) }
                != 0
            {
                let err_str =
                    unsafe { lua_tostring!(L as *mut luaur_vm::records::lua_state::lua_State, -1) };
                let err_str = unsafe { core::ffi::CStr::from_ptr(err_str).to_string_lossy() };
                Some(format(format_args!(
                    "'{}' type function errored at runtime: {}",
                    type_function_name, err_str
                )))
            } else {
                let err_type =
                    unsafe { lua_typename(L as *mut luaur_vm::records::lua_state::lua_State, -1) };
                let err_type = unsafe { core::ffi::CStr::from_ptr(err_type).to_string_lossy() };
                Some(format(format_args!(
                    "'{}' type function errored at runtime: raised an error of type {}",
                    type_function_name, err_type
                )))
            }
        }
    }
}
