#import "Xxhash.h"
#import <React/RCTBridge+Private.h>
#import <ReactCommon/RCTTurboModule.h>
#import <ReactCommon/RCTTurboModuleWithJSIBindings.h>
#import <React/RCTBridge.h>
#import <React/RCTUtils.h>
#import <jsi/jsi.h>

@interface Xxhash () <RCTTurboModule, RCTTurboModuleWithJSIBindings>
@end

@implementation Xxhash
RCT_EXPORT_MODULE(xxhash)

@synthesize bridge = _bridge;
@synthesize methodQueue = _methodQueue;

+ (BOOL)requiresMainQueueSetup {
  return YES;
}

// New Architecture / bridgeless: return the codegen-generated spec TurboModule
// (NativeXxhashSpecJSI). Two reasons over the old generic ObjCTurboModule:
//  1. the spec's methods (hash128/hash64) become reachable from JS as a reliable
//     synchronous fallback (a generic ObjCTurboModule exposes none);
//  2. as a real spec'd TurboModule it is created during runtime setup, so
//     installJSIBindingsWithRuntime: below fires synchronously BEFORE the first
//     JS hash (no async main-queue race).
#ifdef RCT_NEW_ARCH_ENABLED
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
    (const facebook::react::ObjCTurboModule::InitParams &)params {
	return std::make_shared<facebook::react::NativeXxhashSpecJSI>(params);
}
#endif

// Installs __xxhash128 / __xxhash64 with the live jsi::Runtime, WITHOUT depending
// on [RCTBridge currentBridge] — which is nil under bridgeless (RN 0.85), leaving
// the globals uninstalled and making hash128()/hash64() throw "undefined is not
// a function".
- (void)installJSIBindingsWithRuntime:(facebook::jsi::Runtime &)runtime
                          callInvoker:(const std::shared_ptr<facebook::react::CallInvoker> &)callinvoker {
	xxhash::install(&runtime);
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install){
	NSLog(@"Installing JSI bindings for xxhash ...");
	RCTBridge* bridge = [RCTBridge currentBridge];
	RCTCxxBridge* cxxBridge = (RCTCxxBridge*)bridge;

	if (cxxBridge == nil) {
		return @false;
	}

	auto jsiRuntime = (jsi::Runtime*) cxxBridge.runtime;
	if (jsiRuntime == nil) {
		return @false;
	}

	xxhash::install(jsiRuntime);

	return @true;
}

// Synchronous bridge hashers — the JS guard's fallback. On bridgeless the JSI
// globals (__xxhash128/__xxhash64) are installed asynchronously when the module
// is first set up (main queue), so the very first hash at app bootstrap (login)
// can race ahead of the install. These blocking sync methods compute the hash
// through the same xxhash::make_hash_* used by the JSI host functions, so the
// output is bit-identical, and they always work regardless of JSI timing.
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(hash128:(NSString *)input) {
	std::string str = input ? input.UTF8String : "";
	char result[33] = {0};
	xxhash::make_hash_128(str, result);
	return [NSString stringWithUTF8String:result];
}

RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(hash64:(NSString *)input) {
	std::string str = input ? input.UTF8String : "";
	char result[17] = {0};
	xxhash::make_hash_64(str, result);
	return [NSString stringWithUTF8String:result];
}


@end
