#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 "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;

#ifdef __POSIX__
constexpr char kPathSeparator = '/';
constexpr std::string_view kNodeModules = "/node_modules";
#else
constexpr char kPathSeparator = '\\';
constexpr std::string_view kNodeModules = "\\node_modules";
#endif

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 has_manifest = !realm->env()->options()->experimental_policy.empty();
  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[7] = {
      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),
      has_manifest ? ToString(raw_json) : Undefined(isolate),
      ToString(file_path),
  };
  return Array::New(isolate, values, 7);
}

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;
  }

  simdjson::ondemand::document document;
  simdjson::ondemand::object main_object;
  simdjson::error_code error =
      binding_data->json_parser.iterate(package_config.raw_json).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;
      }
    }
  }
  // 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();

  Utf8Value 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());

  auto package_json =
      GetPackageJSON(realm, path.ToString(), is_esm ? &error_context : nullptr);
  if (package_json == nullptr) {
    return;
  }

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

const BindingData::PackageConfig* BindingData::TraverseParent(
    Realm* realm, std::string_view check_path) {
  auto env = realm->env();
  auto root_separator_index = check_path.find_first_of(kPathSeparator);
  size_t separator_index = 0;
  const bool is_permissions_enabled = env->permission()->enabled();

  do {
    separator_index = check_path.find_last_of(kPathSeparator);
    check_path = check_path.substr(0, separator_index);

    // We don't need to try "/"
    if (check_path.empty()) {
      break;
    }

    // Stop the search when the process doesn't have permissions
    // to walk upwards
    if (UNLIKELY(is_permissions_enabled &&
                 !env->permission()->is_granted(
                     permission::PermissionScope::kFileSystemRead,
                     std::string(check_path) + kPathSeparator))) {
      return nullptr;
    }

    // Check if the path ends with `/node_modules`
    if (check_path.size() >= kNodeModules.size() &&
        std::equal(check_path.end() - kNodeModules.size(),
                   check_path.end(),
                   kNodeModules.begin())) {
      return nullptr;
    }

    auto package_json = GetPackageJSON(
        realm,
        std::string(check_path) + kPathSeparator + "package.json",
        nullptr);
    if (package_json != nullptr) {
      return package_json;
    }
  } while (separator_index > root_separator_index);

  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);
  Utf8Value path_value(realm->isolate(), args[0]);
  auto package_json = TraverseParent(realm, path_value.ToStringView());

  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);
  Utf8Value path(realm->isolate(), args[0]);
  auto package_json = TraverseParent(realm, path.ToStringView());

  if (package_json == nullptr) {
    return;
  }

  Local<Value> values[3] = {
      ToV8Value(realm->context(), package_json->type).ToLocalChecked(),
      ToV8Value(realm->context(), package_json->file_path).ToLocalChecked(),
      ToV8Value(realm->context(), package_json->raw_json).ToLocalChecked()};
  args.GetReturnValue().Set(Array::New(realm->isolate(), values, 3));
}

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.size() >= node_modules_package_path.size() &&
        pathname.compare(pathname.size() - node_modules_package_path.size(),
                         node_modules_package_path.size(),
                         node_modules_package_path) == 0) {
      break;
    }

    auto file_url = url::FileURLToPath(realm->env(), *package_json_url);
    CHECK(file_url);
    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 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);
}

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

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

}  // 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)
