#include "node_modules.h"
#include <cstdio>
#include "base_object-inl.h"
#include "node_errors.h"
#include "node_external_reference.h"
#include "node_url.h"
#include "path.h"
#include "permission/permission.h"
#include "permission/permission_base.h"
#include "util-inl.h"
#include "v8-fast-api-calls.h"
#include "v8-function-callback.h"
#include "v8-primitive.h"
#include "v8-value.h"
#include "v8.h"

#include "simdjson.h"

namespace node {
namespace modules {

using v8::Array;
using v8::Context;
using v8::FunctionCallbackInfo;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::NewStringType;
using v8::Object;
using v8::ObjectTemplate;
using v8::Primitive;
using v8::String;
using v8::Undefined;
using v8::Value;

void BindingData::MemoryInfo(MemoryTracker* tracker) const {
  // Do nothing
}

BindingData::BindingData(Realm* realm,
                         v8::Local<v8::Object> object,
                         InternalFieldInfo* info)
    : SnapshotableObject(realm, object, type_int) {}

bool BindingData::PrepareForSerialization(v8::Local<v8::Context> context,
                                          v8::SnapshotCreator* creator) {
  // Return true because we need to maintain the reference to the binding from
  // JS land.
  return true;
}

InternalFieldInfoBase* BindingData::Serialize(int index) {
  DCHECK_IS_SNAPSHOT_SLOT(index);
  InternalFieldInfo* info =
      InternalFieldInfoBase::New<InternalFieldInfo>(type());
  return info;
}

void BindingData::Deserialize(v8::Local<v8::Context> context,
                              v8::Local<v8::Object> holder,
                              int index,
                              InternalFieldInfoBase* info) {
  DCHECK_IS_SNAPSHOT_SLOT(index);
  HandleScope scope(context->GetIsolate());
  Realm* realm = Realm::GetCurrent(context);
  BindingData* binding = realm->AddBindingData<BindingData>(holder);
  CHECK_NOT_NULL(binding);
}

Local<Array> BindingData::PackageConfig::Serialize(Realm* realm) const {
  auto isolate = realm->isolate();
  const auto ToString = [isolate](std::string_view input) -> Local<Primitive> {
    return String::NewFromUtf8(
               isolate, input.data(), NewStringType::kNormal, input.size())
        .ToLocalChecked();
  };
  Local<Value> values[6] = {
      name.has_value() ? ToString(*name) : Undefined(isolate),
      main.has_value() ? ToString(*main) : Undefined(isolate),
      ToString(type),
      imports.has_value() ? ToString(*imports) : Undefined(isolate),
      exports.has_value() ? ToString(*exports) : Undefined(isolate),
      ToString(file_path),
  };
  return Array::New(isolate, values, 6);
}

const BindingData::PackageConfig* BindingData::GetPackageJSON(
    Realm* realm, std::string_view path, ErrorContext* error_context) {
  auto binding_data = realm->GetBindingData<BindingData>();

  auto cache_entry = binding_data->package_configs_.find(path.data());
  if (cache_entry != binding_data->package_configs_.end()) {
    return &cache_entry->second;
  }

  PackageConfig package_config{};
  package_config.file_path = path;
  // No need to exclude BOM since simdjson will skip it.
  if (ReadFileSync(&package_config.raw_json, path.data()) < 0) {
    return nullptr;
  }
  // In some systems, std::string is annotated to generate an
  // AddressSanitizer: container-overflow error when reading beyond the end of
  // the string even when we are still within the capacity of the string.
  // https://github.com/google/sanitizers/wiki/AddressSanitizerContainerOverflow
  // https://github.com/nodejs/node/issues/55584
  // The next lines are a workaround to avoid this false positive.
  size_t json_length = package_config.raw_json.size();
  package_config.raw_json.append(simdjson::SIMDJSON_PADDING, ' ');
  simdjson::padded_string_view json_view(package_config.raw_json.data(),
                                         json_length,
                                         package_config.raw_json.size());
  // End of workaround

  simdjson::ondemand::document document;
  simdjson::ondemand::object main_object;
  simdjson::error_code error =
      binding_data->json_parser.iterate(json_view).get(document);

  const auto throw_invalid_package_config = [error_context, path, realm]() {
    if (error_context == nullptr) {
      THROW_ERR_INVALID_PACKAGE_CONFIG(
          realm->isolate(), "Invalid package config %s.", path.data());
    } else if (error_context->base.has_value()) {
      auto file_url = ada::parse(error_context->base.value());
      CHECK(file_url);
      auto file_path = url::FileURLToPath(realm->env(), *file_url);
      CHECK(file_path.has_value());
      THROW_ERR_INVALID_PACKAGE_CONFIG(
          realm->isolate(),
          "Invalid package config %s while importing \"%s\" from %s.",
          path.data(),
          error_context->specifier.c_str(),
          file_path->c_str());
    } else {
      THROW_ERR_INVALID_PACKAGE_CONFIG(
          realm->isolate(), "Invalid package config %s.", path.data());
    }

    return nullptr;
  };

  if (error || document.get_object().get(main_object)) {
    return throw_invalid_package_config();
  }

  simdjson::ondemand::raw_json_string key;
  simdjson::ondemand::value value;
  std::string_view field_value;
  simdjson::ondemand::json_type field_type;

  for (auto field : main_object) {
    // Throw error if getting key or value fails.
    if (field.key().get(key) || field.value().get(value)) {
      return throw_invalid_package_config();
    }

    // based on coverity using key with == derefs the raw value
    // avoid derefing if its null
    if (key.raw() == nullptr) continue;

    if (key == "name") {
      // Though there is a key "name" with a corresponding value,
      // the value may not be a string or could be an invalid JSON string
      if (value.get_string(package_config.name)) {
        return throw_invalid_package_config();
      }
    } else if (key == "main") {
      // Omit all non-string values
      USE(value.get_string(package_config.main));
    } else if (key == "exports") {
      if (value.type().get(field_type)) {
        return throw_invalid_package_config();
      }
      switch (field_type) {
        case simdjson::ondemand::json_type::object:
        case simdjson::ondemand::json_type::array: {
          if (value.raw_json().get(field_value)) {
            return throw_invalid_package_config();
          }
          package_config.exports = field_value;
          break;
        }
        case simdjson::ondemand::json_type::string: {
          if (value.get_string(package_config.exports)) {
            return throw_invalid_package_config();
          }
          break;
        }
        default:
          break;
      }
    } else if (key == "imports") {
      if (value.type().get(field_type)) {
        return throw_invalid_package_config();
      }
      switch (field_type) {
        case simdjson::ondemand::json_type::array:
        case simdjson::ondemand::json_type::object: {
          if (value.raw_json().get(field_value)) {
            return throw_invalid_package_config();
          }
          package_config.imports = field_value;
          break;
        }
        case simdjson::ondemand::json_type::string: {
          if (value.get_string(package_config.imports)) {
            return throw_invalid_package_config();
          }
          break;
        }
        default:
          break;
      }
    } else if (key == "type") {
      if (value.get_string().get(field_value)) {
        return throw_invalid_package_config();
      }
      // Only update type if it is "commonjs" or "module"
      // The default value is "none" for backward compatibility.
      if (field_value == "commonjs" || field_value == "module") {
        package_config.type = field_value;
      }
    } else if (key == "scripts") {
      if (value.type().get(field_type)) {
        return throw_invalid_package_config();
      }
      switch (field_type) {
        case simdjson::ondemand::json_type::object: {
          if (value.raw_json().get(field_value)) {
            return throw_invalid_package_config();
          }
          package_config.scripts = field_value;
          break;
        }
        default:
          break;
      }
    }
  }
  // package_config could be quite large, so we should move it instead of
  // copying it.
  auto cached = binding_data->package_configs_.insert(
      {std::string(path), std::move(package_config)});

  return &cached.first->second;
}

void BindingData::ReadPackageJSON(const FunctionCallbackInfo<Value>& args) {
  CHECK_GE(args.Length(), 1);  // path, [is_esm, base, specifier]
  CHECK(args[0]->IsString());  // path

  Realm* realm = Realm::GetCurrent(args);
  auto isolate = realm->isolate();

  BufferValue path(isolate, args[0]);
  bool is_esm = args[1]->IsTrue();
  auto error_context = ErrorContext();
  if (is_esm) {
    CHECK(args[2]->IsUndefined() || args[2]->IsString());  // base
    CHECK(args[3]->IsString());                            // specifier

    if (args[2]->IsString()) {
      Utf8Value base_value(isolate, args[2]);
      error_context.base = base_value.ToString();
    }
    Utf8Value specifier(isolate, args[3]);
    error_context.specifier = specifier.ToString();
  }

  THROW_IF_INSUFFICIENT_PERMISSIONS(
      realm->env(),
      permission::PermissionScope::kFileSystemRead,
      path.ToStringView());

  ToNamespacedPath(realm->env(), &path);
  auto package_json = GetPackageJSON(
      realm, path.ToStringView(), is_esm ? &error_context : nullptr);

  if (package_json == nullptr) {
    return;
  }

  args.GetReturnValue().Set(package_json->Serialize(realm));
}

const BindingData::PackageConfig* BindingData::TraverseParent(
    Realm* realm, const std::filesystem::path& check_path) {
  std::filesystem::path current_path = check_path;
  auto env = realm->env();
  const bool is_permissions_enabled = env->permission()->enabled();

  do {
    current_path = current_path.parent_path();

    // We don't need to try "/"
    if (current_path.parent_path() == current_path) {
      break;
    }

    // Stop the search when the process doesn't have permissions
    // to walk upwards
    if (is_permissions_enabled &&
        !env->permission()->is_granted(
            env,
            permission::PermissionScope::kFileSystemRead,
            current_path.generic_string())) [[unlikely]] {
      return nullptr;
    }

    // Check if the path ends with `/node_modules`
    if (current_path.generic_string().ends_with("/node_modules")) {
      return nullptr;
    }

    auto package_json_path = current_path / "package.json";
    auto package_json =
        GetPackageJSON(realm, package_json_path.string(), nullptr);
    if (package_json != nullptr) {
      return package_json;
    }
  } while (true);

  return nullptr;
}

void BindingData::GetNearestParentPackageJSON(
    const v8::FunctionCallbackInfo<v8::Value>& args) {
  CHECK_GE(args.Length(), 1);
  CHECK(args[0]->IsString());

  Realm* realm = Realm::GetCurrent(args);
  BufferValue path_value(realm->isolate(), args[0]);
  // Check if the path has a trailing slash. If so, add it after
  // ToNamespacedPath() as it will be deleted by ToNamespacedPath()
  bool slashCheck = path_value.ToStringView().ends_with(kPathSeparator);

  ToNamespacedPath(realm->env(), &path_value);

  std::string path_value_str = path_value.ToString();
  if (slashCheck) {
    path_value_str.push_back(kPathSeparator);
  }

  auto package_json =
      TraverseParent(realm, std::filesystem::path(path_value_str));

  if (package_json != nullptr) {
    args.GetReturnValue().Set(package_json->Serialize(realm));
  }
}

void BindingData::GetNearestParentPackageJSONType(
    const FunctionCallbackInfo<Value>& args) {
  CHECK_GE(args.Length(), 1);
  CHECK(args[0]->IsString());

  Realm* realm = Realm::GetCurrent(args);
  BufferValue path_value(realm->isolate(), args[0]);
  // Check if the path has a trailing slash. If so, add it after
  // ToNamespacedPath() as it will be deleted by ToNamespacedPath()
  bool slashCheck = path_value.ToStringView().ends_with(kPathSeparator);

  ToNamespacedPath(realm->env(), &path_value);

  std::string path_value_str = path_value.ToString();
  if (slashCheck) {
    path_value_str.push_back(kPathSeparator);
  }

  auto package_json =
      TraverseParent(realm, std::filesystem::path(path_value_str));

  if (package_json == nullptr) {
    return;
  }

  Local<Value> value =
      ToV8Value(realm->context(), package_json->type).ToLocalChecked();
  args.GetReturnValue().Set(value);
}

void BindingData::GetPackageScopeConfig(
    const FunctionCallbackInfo<Value>& args) {
  CHECK_GE(args.Length(), 1);
  CHECK(args[0]->IsString());

  Realm* realm = Realm::GetCurrent(args);
  Utf8Value resolved(realm->isolate(), args[0]);
  auto package_json_url_base = ada::parse(resolved.ToStringView());
  if (!package_json_url_base) {
    url::ThrowInvalidURL(realm->env(), resolved.ToStringView(), std::nullopt);
    return;
  }
  auto package_json_url =
      ada::parse("./package.json", &package_json_url_base.value());
  if (!package_json_url) {
    url::ThrowInvalidURL(realm->env(), "./package.json", resolved.ToString());
    return;
  }

  std::string_view node_modules_package_path = "/node_modules/package.json";
  auto error_context = ErrorContext();
  error_context.is_esm = true;

  // TODO(@anonrig): Rewrite this function and avoid calling URL parser.
  while (true) {
    auto pathname = package_json_url->get_pathname();
    if (pathname.ends_with(node_modules_package_path)) {
      break;
    }

    auto file_url = url::FileURLToPath(realm->env(), *package_json_url);
    if (!file_url) {
      url::ThrowInvalidURL(realm->env(), resolved.ToStringView(), std::nullopt);
      return;
    }
    error_context.specifier = resolved.ToString();
    auto package_json = GetPackageJSON(realm, *file_url, &error_context);
    if (package_json != nullptr) {
      return args.GetReturnValue().Set(package_json->Serialize(realm));
    }

    auto last_href = std::string(package_json_url->get_href());
    auto last_pathname = std::string(package_json_url->get_pathname());
    package_json_url = ada::parse("../package.json", &package_json_url.value());
    if (!package_json_url) {
      url::ThrowInvalidURL(realm->env(), "../package.json", last_href);
      return;
    }

    // Terminates at root where ../package.json equals ../../package.json
    // (can't just check "/package.json" for Windows support).
    if (package_json_url->get_pathname() == last_pathname) {
      break;
    }
  }

  auto package_json_url_as_path =
      url::FileURLToPath(realm->env(), *package_json_url);
  CHECK(package_json_url_as_path);
  return args.GetReturnValue().Set(
      String::NewFromUtf8(realm->isolate(),
                          package_json_url_as_path->c_str(),
                          NewStringType::kNormal,
                          package_json_url_as_path->size())
          .ToLocalChecked());
}

void FlushCompileCache(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Environment* env = Environment::GetCurrent(context);

  if (!args[0]->IsBoolean() && !args[0]->IsUndefined()) {
    THROW_ERR_INVALID_ARG_TYPE(env,
                               "keepDeserializedCache should be a boolean");
    return;
  }
  Debug(env,
        DebugCategory::COMPILE_CACHE,
        "[compile cache] module.flushCompileCache() requested.\n");
  env->FlushCompileCache();
  Debug(env,
        DebugCategory::COMPILE_CACHE,
        "[compile cache] module.flushCompileCache() finished.\n");
}

void EnableCompileCache(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Environment* env = Environment::GetCurrent(context);
  if (!args[0]->IsString()) {
    THROW_ERR_INVALID_ARG_TYPE(env, "cacheDir should be a string");
    return;
  }
  Utf8Value value(isolate, args[0]);
  CompileCacheEnableResult result = env->EnableCompileCache(*value);
  std::vector<Local<Value>> values = {
      v8::Integer::New(isolate, static_cast<uint8_t>(result.status)),
      ToV8Value(context, result.message).ToLocalChecked(),
      ToV8Value(context, result.cache_directory).ToLocalChecked()};
  args.GetReturnValue().Set(Array::New(isolate, values.data(), values.size()));
}

void GetCompileCacheDir(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = args.GetIsolate();
  Local<Context> context = isolate->GetCurrentContext();
  Environment* env = Environment::GetCurrent(context);
  if (!env->use_compile_cache()) {
    args.GetReturnValue().Set(v8::String::Empty(isolate));
    return;
  }
  args.GetReturnValue().Set(
      ToV8Value(context, env->compile_cache_handler()->cache_dir())
          .ToLocalChecked());
}

void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
                                             Local<ObjectTemplate> target) {
  Isolate* isolate = isolate_data->isolate();
  SetMethod(isolate, target, "readPackageJSON", ReadPackageJSON);
  SetMethod(isolate,
            target,
            "getNearestParentPackageJSONType",
            GetNearestParentPackageJSONType);
  SetMethod(isolate,
            target,
            "getNearestParentPackageJSON",
            GetNearestParentPackageJSON);
  SetMethod(isolate, target, "getPackageScopeConfig", GetPackageScopeConfig);
  SetMethod(isolate, target, "enableCompileCache", EnableCompileCache);
  SetMethod(isolate, target, "getCompileCacheDir", GetCompileCacheDir);
  SetMethod(isolate, target, "flushCompileCache", FlushCompileCache);
}

void BindingData::CreatePerContextProperties(Local<Object> target,
                                             Local<Value> unused,
                                             Local<Context> context,
                                             void* priv) {
  Realm* realm = Realm::GetCurrent(context);
  realm->AddBindingData<BindingData>(target);

  std::vector<Local<Value>> compile_cache_status_values;
  Isolate* isolate = context->GetIsolate();

#define V(status)                                                              \
  compile_cache_status_values.push_back(                                       \
      FIXED_ONE_BYTE_STRING(isolate, #status));
  COMPILE_CACHE_STATUS(V)

  USE(target->Set(context,
                  FIXED_ONE_BYTE_STRING(isolate, "compileCacheStatus"),
                  Array::New(isolate,
                             compile_cache_status_values.data(),
                             compile_cache_status_values.size())));
}

void BindingData::RegisterExternalReferences(
    ExternalReferenceRegistry* registry) {
  registry->Register(ReadPackageJSON);
  registry->Register(GetNearestParentPackageJSONType);
  registry->Register(GetNearestParentPackageJSON);
  registry->Register(GetPackageScopeConfig);
  registry->Register(EnableCompileCache);
  registry->Register(GetCompileCacheDir);
  registry->Register(FlushCompileCache);
}

}  // namespace modules
}  // namespace node

NODE_BINDING_CONTEXT_AWARE_INTERNAL(
    modules, node::modules::BindingData::CreatePerContextProperties)
NODE_BINDING_PER_ISOLATE_INIT(
    modules, node::modules::BindingData::CreatePerIsolateProperties)
NODE_BINDING_EXTERNAL_REFERENCE(
    modules, node::modules::BindingData::RegisterExternalReferences)
