/*
 * Copyright © Dynamsoft Corporation. All rights reserved.
 *
 */

#import <React/RCTBridge+Private.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTViewManager.h>
#import <DynamsoftCaptureVisionBundle/DynamsoftCaptureVisionBundle.h>
#import <DynamsoftCaptureVisionSpec/DynamsoftCaptureVisionSpec.h>
#import "DSImageData+HostObject.h"
#if RCT_NEW_ARCH_ENABLED
#import <ReactCommon/RCTTurboModule.h>
#import <ReactCommon/RCTTurboModuleWithJSIBindings.h>
#endif

// Auto-generated Objective-C interface for this pod's Swift sources. The header name is
// derived from the pod's module name (hyphens become underscores) — verify against the
// build log if this ever fails to resolve.
#if __has_include("dynamsoft_capture_vision_react_native-Swift.h")
#import "dynamsoft_capture_vision_react_native-Swift.h"
#else
#import <dynamsoft_capture_vision_react_native/dynamsoft_capture_vision_react_native-Swift.h>
#endif

using namespace facebook::jsi;
using namespace facebook;
using namespace std;

static void install(jsi::Runtime &jsiRuntime, RNDynamsoftImageEditorViewManager *rnEditorViewManager);

@interface RNDynamsoftImageEditorViewManager (JSIBindings)
#if RCT_NEW_ARCH_ENABLED
<RCTTurboModule, RCTTurboModuleWithJSIBindings>
#endif
@end

@implementation RNDynamsoftImageEditorViewManager (JSIBindings)

#pragma mark - Global JSI
#if RCT_NEW_ARCH_ENABLED
// New Architecture: RN automatically calls this once the TurboModule is created,
// handing us a valid jsi::Runtime (no bridge/RCTCxxBridge access needed).
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const facebook::react::ObjCTurboModule::InitParams &)params
{
    return std::make_shared<facebook::react::NativeDynamsoftImageEditorViewModuleSpecJSI>(params);
}

- (void)installJSIBindingsWithRuntime:(facebook::jsi::Runtime &)runtime
                          callInvoker:(const std::shared_ptr<facebook::react::CallInvoker> &)callInvoker
{
    install(runtime, self);
}

// Kept as a no-op so existing JS call sites (ImageEditorViewModule.install()) remain harmless.
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
{
    return @true;
}
#else
// Legacy Architecture only.
RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(install)
{
    RCTBridge *bridge = self.bridge;

    if ([bridge respondsToSelector:NSSelectorFromString(@"parentBridge")]) {
        bridge = [bridge valueForKey:@"parentBridge"];
    }

    RCTCxxBridge *cxxBridge = (RCTCxxBridge *)bridge;
    if (cxxBridge == nil || cxxBridge.runtime == nil) {
        return @false;
    }

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

    install(*(facebook::jsi::Runtime *)cxxBridge.runtime, self);
    return @true;
}
#endif

@end

// --- Helper Function (Assumed to be accessible, copied here for completeness) ---
static void installHostFunction(
    jsi::Runtime &jsiRuntime,
    const char* name,
    unsigned int argCount,
    HostFunctionType hostFunction) {

    auto func = Function::createFromHostFunction(
        jsiRuntime,
        PropNameID::forAscii(jsiRuntime, name),
        argCount,
        std::move(hostFunction)
    );
    jsiRuntime.global().setProperty(jsiRuntime, name, std::move(func));
}

// --- JSI Installation Logic ---
static void install(jsi::Runtime &jsiRuntime, RNDynamsoftImageEditorViewManager *rnEditorViewManager) {

    // 1. editorView_setOriginalImage(viewTag, imageDataHostObject)
    installHostFunction(jsiRuntime, "editorView_setOriginalImage", 2,
        [rnEditorViewManager](Runtime &runtime, const Value &thisValue, const Value *arguments, size_t count) -> Value {

            // Argument Validation & Type Check
            if (count != 2 || !arguments[0].isNumber() || !arguments[1].isObject()) {
                return Value(false);
            }

            // Extract View Tag (JS number)
            double tag = arguments[0].getNumber();
            NSNumber *viewTag = @(tag); // Convert to NSNumber for Objective-C method

            // Extract Image Data Host Object (Requires runtime for getObject)
            Object obj = arguments[1].getObject(runtime);

            // Check if it's the specific Host Object type (Requires runtime for isHostObject)
            if (obj.isHostObject<ImageDataHostObject>(runtime)) {
                // Safely convert Host Object to DSImageData
                ImageDataHostObject hostObject = ImageDataHostObject::getHOFromObject(runtime, obj);
                DSImageData *data = [DSImageData imageDataFromHostObject:hostObject];

                // Call the Swift view manager method
                [rnEditorViewManager trySetImageDataWithTag:viewTag data:data attempt:1];

                return Value(true);
            }

            return Value(false);
        }
    );
}
