#!/bin/bash

# Script to automatically fix all generated files to include both nostr-sdk and cdk dependencies
# Fixes: C++ bindings, TypeScript exports, podspec frameworks, and iOS header imports
set -e

# Cross-platform sed -i compatibility
sed_inplace() {
    if [[ "$OSTYPE" == "darwin"* ]]; then
        sed -i '' "$@"
    else
        sed -i "$@"
    fi
}

# Parse command line arguments
SKIP_IOS=false
while [[ $# -gt 0 ]]; do
    case $1 in
        --skip-ios)
            SKIP_IOS=true
            shift
            ;;
        *)
            echo "Unknown option: $1"
            echo "Usage: $0 [--skip-ios]"
            exit 1
            ;;
    esac
done

CPP_FILE="cpp/kashir.cpp"
TS_FILE="src/index.tsx"

echo "🔧 Fixing files to include both nostr-sdk and cdk dependencies..."
echo "   - C++ bindings"
echo "   - TypeScript exports"
if [[ $SKIP_IOS == true ]]; then
    echo "   - Android CMakeLists.txt"
fi
if [[ $SKIP_IOS == false ]]; then
    echo "   - Auto-generated podspec frameworks and iOS header imports"
else
    echo "   - Auto-generated podspec frameworks and iOS header imports (SKIPPED - iOS-specific)"
fi

if [ ! -f "$CPP_FILE" ]; then
    echo "❌ C++ file not found: $CPP_FILE"
    exit 1
fi

# Check if the file already has both dependencies
has_nostr_include=$(grep -c "generated/nostr_sdk.hpp" "$CPP_FILE" || true)
has_cdk_include=$(grep -c "generated/cdk_ffi.hpp" "$CPP_FILE" || true)
has_nostr_register=$(grep -c "NativeNostrSdk::registerModule" "$CPP_FILE" || true)
has_cdk_register=$(grep -c "NativeCdkFfi::registerModule" "$CPP_FILE" || true)

echo "📊 Current state:"
echo "   - Nostr include: $has_nostr_include"
echo "   - CDK include: $has_cdk_include"
echo "   - Nostr register: $has_nostr_register"
echo "   - CDK register: $has_cdk_register"

# Check if C++ needs fixing
cpp_needs_fix=false
if [[ $has_nostr_include -eq 0 || $has_cdk_include -eq 0 || $has_nostr_register -eq 0 || $has_cdk_register -eq 0 ]]; then
    cpp_needs_fix=true
fi

if [[ $cpp_needs_fix == true ]]; then
    echo "🛠️  Updating C++ file to include both dependencies..."

# Create the fixed content
cat > "$CPP_FILE" << 'EOF'
// Generated by uniffi-bindgen-react-native
#include "kashir.h"
#include "generated/nostr_sdk.hpp"
#include "generated/cdk_ffi.hpp"

namespace kashir {
	using namespace facebook;

	uint8_t installRustCrate(jsi::Runtime &runtime, std::shared_ptr<react::CallInvoker> callInvoker) {
		NativeNostrSdk::registerModule(runtime, callInvoker);
		NativeCdkFfi::registerModule(runtime, callInvoker);
		return true;
	}

	uint8_t cleanupRustCrate(jsi::Runtime &runtime) {
		return false;
	}
}
EOF

    echo "✅ Fixed C++ file to include both nostr-sdk and cdk dependencies"
    echo "   - Added both header includes"
    echo "   - Added both module registrations"
else
    echo "✅ C++ file already has both dependencies configured"
fi

# Now fix the TypeScript index file
echo ""
echo "🔧 Fixing TypeScript index file..."

if [ ! -f "$TS_FILE" ]; then
    echo "❌ TypeScript file not found: $TS_FILE"
    exit 1
fi

# Check if the TypeScript file already has both dependencies
has_nostr_export=$(grep -c "export \* from './generated/nostr_sdk'" "$TS_FILE" || true)
has_cdk_export=$(grep -c "export \* from './generated/cdk_ffi'" "$TS_FILE" || true)
has_nostr_import=$(grep -c "import \* as nostr_sdk" "$TS_FILE" || true)
has_cdk_import=$(grep -c "import \* as cdk_ffi" "$TS_FILE" || true)
has_nostr_init=$(grep -c "nostr_sdk.default.initialize()" "$TS_FILE" || true)
has_cdk_init=$(grep -c "cdk_ffi.default.initialize()" "$TS_FILE" || true)

echo "📊 TypeScript current state:"
echo "   - Nostr export: $has_nostr_export"
echo "   - CDK export: $has_cdk_export"
echo "   - Nostr import: $has_nostr_import"
echo "   - CDK import: $has_cdk_import"
echo "   - Nostr init: $has_nostr_init"
echo "   - CDK init: $has_cdk_init"

# Check if TypeScript needs fixing
ts_needs_fix=false
if [[ $has_nostr_export -eq 0 || $has_cdk_export -eq 0 || $has_nostr_import -eq 0 || $has_cdk_import -eq 0 || $has_nostr_init -eq 0 || $has_cdk_init -eq 0 ]]; then
    ts_needs_fix=true
fi

if [[ $ts_needs_fix == true ]]; then
    echo "🛠️  Updating TypeScript file to include both dependencies..."

# Create the fixed TypeScript content
cat > "$TS_FILE" << 'EOF'
// Generated by uniffi-bindgen-react-native
import installer from './NativeKashir';

// Register the rust crate with Hermes
// - the boolean flag ensures this loads exactly once, even if the JS
//   code is reloaded (e.g. during development with metro).
let rustInstalled = false;
if (!rustInstalled) {
  installer.installRustCrate();
  rustInstalled = true;
}

// Export the generated bindings to the app.
export * from './generated/nostr_sdk';
export * from './generated/cdk_ffi';

// Now import the bindings so we can:
// - intialize them
// - export them as namespaced objects as the default export.
import * as nostr_sdk from './generated/nostr_sdk';
import * as cdk_ffi from './generated/cdk_ffi';

// Initialize the generated bindings: mostly checksums, but also callbacks.
// - the boolean flag ensures this loads exactly once, even if the JS code
//   is reloaded (e.g. during development with metro).
let initialized = false;
if (!initialized) {
  nostr_sdk.default.initialize();
  cdk_ffi.default.initialize();
  initialized = true;
}

// Export the crates as individually namespaced objects.
export default {
  nostr_sdk,
  cdk_ffi,
};
EOF

    echo "✅ Fixed TypeScript file to include both nostr-sdk and cdk dependencies"
    echo "   - Added both exports"
    echo "   - Added both imports" 
    echo "   - Added both initializations"
    echo "   - Added both to default export"
else
    echo "✅ TypeScript file already has both dependencies configured"
fi

# Fix the Android CMakeLists.txt file (Android-specific)
if [[ $SKIP_IOS == true ]]; then
    echo ""
    echo "🔧 Fixing Android CMakeLists.txt..."
CMAKE_FILE="android/CMakeLists.txt"
if [ -f "$CMAKE_FILE" ]; then
    # Check if it already has both dependencies
    has_nostr_cpp=$(grep -c "../cpp/generated/nostr_sdk.cpp" "$CMAKE_FILE" || true)
    has_cdk_cpp=$(grep -c "../cpp/generated/cdk_ffi.cpp" "$CMAKE_FILE" || true)
    has_nostr_lib=$(grep -c "libnostr_sdk_ffi.a" "$CMAKE_FILE" || true)
    has_cdk_lib=$(grep -c "libcdk_ffi.a" "$CMAKE_FILE" || true)
    
    echo "📊 CMakeLists.txt current state:"
    echo "   - Nostr SDK cpp: $has_nostr_cpp"
    echo "   - CDK cpp: $has_cdk_cpp"
    echo "   - Nostr SDK lib: $has_nostr_lib"
    echo "   - CDK lib: $has_cdk_lib"
    
    cmake_needs_fix=false
    if [[ $has_nostr_cpp -eq 0 || $has_cdk_cpp -eq 0 || $has_nostr_lib -eq 0 || $has_cdk_lib -eq 0 ]]; then
        cmake_needs_fix=true
    fi
    
    if [[ $cmake_needs_fix == true ]]; then
        echo "🛠️  Updating CMakeLists.txt to include both dependencies..."
        
        # Add nostr_sdk cpp file if missing
        if [[ $has_nostr_cpp -eq 0 && $has_cdk_cpp -eq 1 ]]; then
            sed_inplace '/..\/cpp\/generated\/cdk_ffi.cpp/i\
    ../cpp/generated/nostr_sdk.cpp
' "$CMAKE_FILE"
        fi
        
                 # Fix library paths if they're pointing to wrong libraries
        if [[ $has_nostr_lib -eq 0 && $has_cdk_lib -gt 0 ]]; then
            # Change MY_RUST_LIB from cdk to nostr-sdk
            sed_inplace 's/libcdk_ffi\.a/libnostr_sdk_ffi.a/' "$CMAKE_FILE"
            
            # Add CDK library definition after the rust lib
            sed_inplace '/set_target_properties(my_rust_lib PROPERTIES IMPORTED_LOCATION \${MY_RUST_LIB})/a\
\
cmake_path(\
  SET MY_CDK_LIB\
  ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libcdk_ffi.a\
  NORMALIZE\
)\
add_library(my_cdk_lib STATIC IMPORTED)\
set_target_properties(my_cdk_lib PROPERTIES IMPORTED_LOCATION ${MY_CDK_LIB})
' "$CMAKE_FILE"
            
            # Add CDK library to target_link_libraries (only in the final target_link_libraries section)
            sed_inplace '/target_link_libraries(/,/my_rust_lib/s/my_rust_lib/my_rust_lib\
  my_cdk_lib/' "$CMAKE_FILE"
        fi
        
        # Add linker flag to allow multiple definitions (resolves secp256k1 symbol conflicts)
        has_linker_flag=$(grep -c "allow-multiple-definition" "$CMAKE_FILE" || true)
        if [[ $has_linker_flag -eq 0 ]]; then
            # Add the linker flag after the last set_target_properties line
            sed_inplace '/set_target_properties(my_cdk_lib PROPERTIES IMPORTED_LOCATION \${MY_CDK_LIB})/a\
\
# Allow multiple definitions to resolve secp256k1 symbol conflicts between nostr-sdk and cdk\
set_target_properties(kashir PROPERTIES\
  LINK_FLAGS "-Wl,--allow-multiple-definition"\
)
' "$CMAKE_FILE"
            echo "✅ Added linker flag to allow multiple definitions"
        else
            echo "✅ Linker flag already present"
        fi
        
        echo "✅ Fixed CMakeLists.txt to include both dependencies"
        echo "   - Added both cpp and library files"
        echo "   - Added linker flag for symbol conflict resolution"
    else
        echo "✅ CMakeLists.txt already has both dependencies configured"
    fi
else
    echo "⚠️  CMakeLists.txt not found: $CMAKE_FILE"
fi
fi  # End of Android-specific CMakeLists.txt fixing

# Fix the auto-generated podspec to include both frameworks (iOS-specific)
if [[ $SKIP_IOS == false ]]; then
    echo ""
    echo "🔧 Fixing auto-generated podspec to include both frameworks..."
    AUTO_GENERATED_PODSPEC="kashir.podspec"
    if [ -f "$AUTO_GENERATED_PODSPEC" ]; then
        # Check if it needs both frameworks
        has_both_frameworks=$(grep -c '"NostrSdkFramework.xcframework", "CdkFramework.xcframework"' "$AUTO_GENERATED_PODSPEC" || true)
        
        if [[ $has_both_frameworks -eq 0 ]]; then
            echo "🛠️  Updating auto-generated podspec to include both frameworks..."
            
            # Replace the vendored_frameworks line to include both
            sed_inplace 's/s\.vendored_frameworks = "CdkFramework\.xcframework"/s.vendored_frameworks = "NostrSdkFramework.xcframework", "CdkFramework.xcframework"/' "$AUTO_GENERATED_PODSPEC"
            
            echo "✅ Fixed auto-generated podspec to include both frameworks"
            echo "   - NostrSdkFramework.xcframework"
            echo "   - CdkFramework.xcframework"
        else
            echo "✅ Auto-generated podspec already has both frameworks"
        fi
        
        # Fix iOS header import to use relative path (resolves case-insensitive filename collision)
        IOS_HEADER_FILE="ios/Kashir.h"
        if [ -f "$IOS_HEADER_FILE" ]; then
            has_relative_import=$(grep -c '#import "../cpp/kashir.h"' "$IOS_HEADER_FILE" || true)
            has_direct_import=$(grep -c '#import "kashir.h"' "$IOS_HEADER_FILE" || true)
            
            if [[ $has_direct_import -gt 0 && $has_relative_import -eq 0 ]]; then
                echo "🛠️  Fixing iOS header import to use relative path..."
                sed_inplace 's|#import "kashir.h"|#import "../cpp/kashir.h"|' "$IOS_HEADER_FILE"
                echo "✅ Fixed iOS header to use relative path: #import \"../cpp/kashir.h\""
                echo "   - Resolves case-insensitive filename collision between ios/Kashir.h and cpp/kashir.h"
            else
                echo "✅ iOS header already uses relative path import"
            fi
        else
            echo "⚠️  iOS header file not found: $IOS_HEADER_FILE"
            echo "   This is expected on first run before UBRN generates it"
        fi
    else
        echo "⚠️  Auto-generated podspec not found: $AUTO_GENERATED_PODSPEC"
        echo "   This is expected on first run before UBRN generates it"
    fi
else
    echo ""
    echo "⏭️  Skipping auto-generated podspec file (iOS-specific)"
fi

