import { useCallback, useState, useRef, useEffect } from 'react';
// import { usePersSDK } from '../providers/PersSDKProvider';
import { SigningStatus } from '@explorins/pers-signer';
// Re-export signing status types from signer SDK for convenience
export { SigningStatus };
// Lazy-loaded signer SDK factory - initialized on first use to avoid native module timing issues
let _createPersSignerSDK = null;
let _signerInitAttempted = false;
/**
 * Lazily load the PERS Signer SDK.
 *
 * Supports customer pre-initialization via global.__PersSigner for environments
 * where native module timing is unpredictable (e.g., certain React Native setups).
 *
 * @returns The createPersSignerSDK function or null if unavailable
 */
function getSignerSDKFactory() {
    if (_signerInitAttempted) {
        // Already tried - return cached result (could be null if failed)
        return _createPersSignerSDK;
    }
    _signerInitAttempted = true;
    // Check for customer pre-initialized global (for native module timing issues)
    if (typeof global !== 'undefined' && global.__PersSigner?.createPersSignerSDK) {
        _createPersSignerSDK = global.__PersSigner.createPersSignerSDK;
        return _createPersSignerSDK;
    }
    // Standard lazy load
    try {
        const signerModule = require('@explorins/pers-signer/react-native');
        _createPersSignerSDK = signerModule.createPersSignerSDK;
        return _createPersSignerSDK;
    }
    catch (error) {
        console.warn('[useTransactionSigner] PERS Signer SDK not available:', error.message);
        console.warn('[useTransactionSigner] Real blockchain signing will not be available');
        console.warn('[useTransactionSigner] Tip: If timing issues, pre-initialize in index.js: global.__PersSigner = require("@explorins/pers-signer/react-native")');
        _createPersSignerSDK = null; // Mark as unavailable
        return null;
    }
}
// Constants - TODO: Move to environment config later
const DEFAULT_ETHERS_PROVIDER = "https://sepolia.infura.io/v3/2781b4b5242343d5b0954c98f287b29e";
/**
 * React Native hook for blockchain transaction signing using PERS Signer SDK
 *
 * This hook provides a complete blockchain transaction signing solution for React Native
 * applications, integrating with the PERS ecosystem for tourism loyalty and reward systems.
 * It automatically handles WebAuthn authentication, transaction preparation, signing, and
 * blockchain submission in a single convenient interface.
 *
 * **Features:**
 * - Automatic WebAuthn provider initialization for React Native
 * - 5-minute authentication caching to reduce repeated logins
 * - Complete transaction lifecycle management (sign + submit)
 * - Comprehensive error handling with detailed error messages
 * - Real-time status monitoring for UI feedback
 * - Automatic retry logic for network failures
 *
 * **Underlying SDK Methods:**
 * The hook uses the PERS Signer SDK which provides 5 core methods:
 * 1. `loginUser(jwtToken)` - Authenticate user with 5-minute caching
 * 2. `signTransaction(signingData, jwtToken)` - Sign transactions with auto-login
 * 3. `submitTransaction(signingResult, jwtToken)` - Submit signed transactions
 * 4. `signPersTransaction(jwtToken)` - Legacy one-liner for backward compatibility
 * 5. `signAndSubmitPersTransaction(jwtToken)` - Complete sign + submit flow (used by this hook)
 *
 * **Security:**
 * - WebAuthn-based secure authentication (no passwords stored)
 * - JWT token validation and expiration checking
 * - Secure transaction signing using device biometrics/PIN
 * - No sensitive data stored locally
 *
 * @returns {TransactionSignerHook} Hook interface with signing methods and status
 *
 * @example
 * **Basic Usage:**
 * ```typescript
 * import { useTransactionSigner } from '@explorins/pers-sdk-react-native';
 *
 * function TransactionScreen() {
 *   const {
 *     signAndSubmitTransactionWithJWT,
 *     isSignerAvailable,
 *     isSignerInitialized
 *   } = useTransactionSigner();
 *
 *   const handleSign = async (jwtFromRedemption: string) => {
 *     if (!isSignerAvailable) {
 *       console.error('Signer not available');
 *       return;
 *     }
 *
 *     try {
 *       const result = await signAndSubmitTransactionWithJWT(jwtFromRedemption);
 *       if (result.success) {
 *         console.log('Transaction completed:', result.transactionHash);
 *         // Handle successful transaction
 *         if (result.shouldRedirect && result.redirectUrl) {
 *           // Navigate to success page or external URL
 *         }
 *       }
 *     } catch (error) {
 *       console.error('Transaction failed:', error.message);
 *       // Handle error (show user-friendly message)
 *     }
 *   };
 *
 *   return (
 *     <View style={styles.container}>
 *       <TouchableOpacity
 *         onPress={() => handleSign(redeemJWT)}
 *         disabled={!isSignerAvailable}
 *         style={[styles.button, !isSignerAvailable && styles.disabled]}
 *       >
 *         <Text style={styles.buttonText}>
 *           {isSignerInitialized ? 'Sign Transaction' : 'Initializing...'}
 *         </Text>
 *       </TouchableOpacity>
 *     </View>
 *   );
 * }
 * ```
 *
 * @example
 * **Advanced Usage with Error Handling:**
 * ```typescript
 * function AdvancedTransactionComponent() {
 *   const [isLoading, setIsLoading] = useState(false);
 *   const [error, setError] = useState<string | null>(null);
 *   const { signAndSubmitTransactionWithJWT, isSignerAvailable } = useTransactionSigner();
 *
 *   const handleTransaction = async (jwt: string) => {
 *     setIsLoading(true);
 *     setError(null);
 *
 *     try {
 *       const result = await signAndSubmitTransactionWithJWT(jwt);
 *
 *       if (result.success) {
 *         // Success handling
 *         Alert.alert(
 *           'Success',
 *           `Transaction completed!\nHash: ${result.transactionHash}`
 *         );
 *       } else {
 *         throw new Error(result.error || 'Transaction failed');
 *       }
 *     } catch (err) {
 *       const errorMessage = err instanceof Error ? err.message : 'Unknown error';
 *       setError(errorMessage);
 *
 *       // Different error handling based on error type
 *       if (errorMessage.includes('expired')) {
 *         Alert.alert('Session Expired', 'Please log in again');
 *       } else if (errorMessage.includes('network')) {
 *         Alert.alert('Network Error', 'Please check your connection');
 *       } else {
 *         Alert.alert('Transaction Failed', errorMessage);
 *       }
 *     } finally {
 *       setIsLoading(false);
 *     }
 *   };
 *
 *   return (
 *     <View>
 *       {error && (
 *         <Text style={styles.errorText}>{error}</Text>
 *       )}
 *       <TouchableOpacity
 *         onPress={() => handleTransaction(jwtToken)}
 *         disabled={!isSignerAvailable || isLoading}
 *       >
 *         <Text>
 *           {isLoading ? 'Processing...' : 'Sign & Submit Transaction'}
 *         </Text>
 *       </TouchableOpacity>
 *     </View>
 *   );
 * }
 * ```
 *
 * @example
 * **Integration with PERS SDK:**
 * ```typescript
 * import { usePersSDK } from '@explorins/pers-sdk-react-native';
 * import { useTransactionSigner } from '@explorins/pers-sdk-react-native';
 *
 * function RedemptionFlow() {
 *   const { user, redeemTokens } = usePersSDK();
 *   const { signAndSubmitTransactionWithJWT } = useTransactionSigner();
 *
 *   const handleRedemption = async (tokenAmount: number) => {
 *     try {
 *       // Step 1: Create redemption with PERS SDK
 *       const redemption = await redeemTokens({
 *         tokenAmount,
 *         destinationAddress: user?.walletAddress
 *       });
 *
 *       // Step 2: Sign and submit transaction
 *       const txResult = await signAndSubmitTransactionWithJWT(redemption.jwtToken);
 *
 *       if (txResult.success) {
 *         console.log('Redemption completed:', txResult.transactionHash);
 *       }
 *     } catch (error) {
 *       console.error('Redemption failed:', error);
 *     }
 *   };
 * }
 * ```
 *
 * @see {@link SubmissionResult} for transaction result structure
 * @see {@link TransactionSigningResult} for signing result details
 * @see {@link AuthenticatedUser} for user authentication data
 *
 * @since 1.5.0
 */
export const useTransactionSigner = () => {
    // const { isInitialized, isAuthenticated, user } = usePersSDK();
    const [isSignerInitialized, setIsSignerInitialized] = useState(false);
    const [currentStatus, setCurrentStatus] = useState(null);
    const [statusMessage, setStatusMessage] = useState(null);
    const signerSDKRef = useRef(null);
    // Auto-initialize signer SDK when PERS SDK is ready
    useEffect(() => {
        const initializeSignerSDK = async () => {
            const createPersSignerSDK = getSignerSDKFactory();
            if (!createPersSignerSDK) {
                console.warn('[useTransactionSigner] Signer SDK not available');
                return;
            }
            try {
                // React Native createPersSignerSDK automatically includes WebAuthn provider
                const signerSDK = await createPersSignerSDK({
                    ethersProviderUrl: DEFAULT_ETHERS_PROVIDER,
                    relyingPartyName: 'PERS React Native App'
                });
                signerSDKRef.current = signerSDK;
                setIsSignerInitialized(true);
            }
            catch (error) {
                console.error('[useTransactionSigner] Failed to initialize signer SDK:', error);
            }
        };
        if (!isSignerInitialized) {
            initializeSignerSDK();
        }
    }, [isSignerInitialized]);
    /**
     * Sign and submit a blockchain transaction using JWT token
     *
     * This is the main method for executing blockchain transactions in React Native.
     * It handles the complete transaction lifecycle: authentication, signing, and
     * blockchain submission in a single call.
     *
     * **Process Flow:**
     * 1. Validates the JWT token and extracts transaction data
     * 2. Authenticates the user using WebAuthn (cached for 5 minutes)
     * 3. Fetches transaction data from PERS backend
     * 4. Signs the transaction using device security (biometrics/PIN)
     * 5. Submits the signed transaction to the blockchain
     * 6. Returns detailed result with transaction hash and status
     *
     * **Security Features:**
     * - JWT token validation and expiration checking
     * - WebAuthn authentication with device biometrics
     * - Secure transaction signing without exposing private keys
     * - Automatic session management with secure caching
     *
     * @param {string} jwt - JWT token containing transaction ID and user information
     *   Must include: `transactionId`, `identifierEmail`, `tenantId`
     * @param {StatusCallback} [onStatusUpdate] - Optional callback for real-time status updates
     * @returns {Promise<SubmissionResult>} Complete transaction result
     *
     * @throws {Error} 'Transaction signer not initialized' - Hook not ready
     * @throws {Error} 'PERS Signer SDK not available' - SDK installation issue
     * @throws {Error} 'Invalid or expired JWT token' - Token validation failed
     * @throws {Error} 'Authentication failed' - WebAuthn authentication failed
     * @throws {Error} 'Transaction signing failed' - Signing process failed
     * @throws {Error} 'Transaction submission failed' - Blockchain submission failed
     *
     * @example
     * **Basic Transaction:**
     * ```typescript
     * const { signAndSubmitTransactionWithJWT } = useTransactionSigner();
     *
     * const result = await signAndSubmitTransactionWithJWT(jwtToken);
     * if (result.success) {
     *   console.log('Transaction Hash:', result.transactionHash);
     *   console.log('Blockchain explorer: [Chain-specific explorer URL]');
     * }
     * ```
     *
     * @example
     * **With Status Updates:**
     * ```typescript
     * const result = await signAndSubmitTransactionWithJWT(jwtToken, (status, message) => {
     *   console.log(`Status: ${status} - ${message}`);
     *   setStatusText(message);
     * });
     * ```
     *
     * @example
     * **With Error Handling:**
     * ```typescript
     * try {
     *   const result = await signAndSubmitTransactionWithJWT(redeemJWT);
     *
     *   if (result.success) {
     *     // Transaction successful
     *     setTransactionHash(result.transactionHash);
     *
     *     if (result.shouldRedirect && result.redirectUrl) {
     *       // Handle post-transaction redirect
     *       Linking.openURL(result.redirectUrl);
     *     }
     *   } else {
     *     // Transaction failed but didn't throw
     *     setError(result.error || 'Transaction failed');
     *   }
     * } catch (error) {
     *   // Handle different error types
     *   if (error.message.includes('expired')) {
     *     // Token expired - redirect to login
     *     navigation.navigate('Login');
     *   } else if (error.message.includes('network')) {
     *     // Network error - suggest retry
     *     setError('Network error. Please try again.');
     *   } else {
     *     // Other errors
     *     setError(error.message);
     *   }
     * }
     * ```
     *
     * @see {@link SubmissionResult} for detailed result structure
     */
    const signAndSubmitTransactionWithJWT = useCallback(async (jwt, onStatusUpdate) => {
        if (!isSignerInitialized || !signerSDKRef.current) {
            throw new Error('Transaction signer not initialized');
        }
        if (!getSignerSDKFactory()) {
            throw new Error('PERS Signer SDK not available. Blockchain signing is not supported.');
        }
        // Create status callback wrapper that updates both hook state and calls user callback
        const statusCallback = {
            onStatusUpdate: (status, message, data) => {
                setCurrentStatus(status);
                setStatusMessage(message);
                onStatusUpdate?.(status, message, data);
            }
        };
        try {
            // Use the actual SDK method that handles the complete sign + submit flow
            const submissionResult = await signerSDKRef.current.signAndSubmitPersTransaction(jwt, statusCallback);
            return submissionResult;
        }
        catch (error) {
            console.error('[useTransactionSigner] JWT transaction signing failed:', error);
            setCurrentStatus(SigningStatus.ERROR);
            setStatusMessage(error instanceof Error ? error.message : 'Transaction failed');
            throw error; // Re-throw to maintain error handling upstream
        }
    }, [isSignerInitialized]);
    /**
     * Sign a PERS transaction without submitting (for POS flows with QR codes)
     *
     * This method signs the transaction but does NOT submit it to the blockchain.
     * Instead, it returns the signature which can be displayed as a QR code for
     * the business to scan and submit.
     *
     * **Use Case:** Point-of-Sale (POS) flows where:
     * 1. User signs the transaction
     * 2. App generates QR code with signature
     * 3. Business scans QR code
     * 4. Business submits transaction to blockchain
     *
     * @param {string} jwt - JWT token with transaction and user data
     * @param {StatusCallback} [onStatusUpdate] - Optional callback for status updates
     * @returns {Promise<TransactionSigningResult>} Signing result with signature for QR code
     *
     * @example
     * ```typescript
     * const { signPersTransaction } = useTransactionSigner();
     *
     * const result = await signPersTransaction(jwtToken);
     * if (result.success) {
     *   const qrData = {
     *     transactionId: result.transactionId,
     *     signature: result.signature,
     *     transactionFormat: result.signingData.format,
     *     txType: 'PENDING_SUBMISSION'
     *   };
     *   // Display QR code with qrData
     * }
     * ```
     */
    const signPersTransaction = useCallback(async (jwt, onStatusUpdate) => {
        if (!isSignerInitialized || !signerSDKRef.current) {
            throw new Error('Signer SDK not initialized');
        }
        // Create status callback wrapper
        const statusCallback = {
            onStatusUpdate: (status, message, data) => {
                setCurrentStatus(status);
                setStatusMessage(message);
                onStatusUpdate?.(status, message, data);
            }
        };
        try {
            // Use the SDK's sign-only method
            const signingResult = await signerSDKRef.current.signPersTransaction(jwt, statusCallback);
            return signingResult;
        }
        catch (error) {
            console.error('[useTransactionSigner] Sign-only transaction failed:', error);
            setCurrentStatus(SigningStatus.ERROR);
            setStatusMessage(error instanceof Error ? error.message : 'Signing failed');
            throw error;
        }
    }, [isSignerInitialized]);
    return {
        /**
         * Sign and submit a blockchain transaction using JWT token
         *
         * Main method for executing blockchain transactions. Handles complete flow
         * from authentication to blockchain submission in a single call.
         *
         * @param {string} jwt - JWT token with transaction and user data
         * @param {StatusCallback} [onStatusUpdate] - Optional callback for real-time status updates
         * @returns {Promise<SubmissionResult>} Transaction result with hash and status
         */
        signAndSubmitTransactionWithJWT,
        /**
         * Sign a transaction without submitting (for POS flows)
         *
         * Signs the transaction and returns the signature without submitting to blockchain.
         * Use this for Point-of-Sale flows where the business scans a QR code and submits.
         *
         * @param {string} jwt - JWT token with transaction and user data
         * @param {StatusCallback} [onStatusUpdate] - Optional callback for status updates
         * @returns {Promise<TransactionSigningResult>} Signing result with signature for QR code
         */
        signPersTransaction,
        /**
         * Whether the transaction signer SDK has been successfully initialized
         *
         * Use this to show loading states while the signer is being set up.
         * When `false`, the signer is still initializing and transactions cannot be processed.
         *
         * @example
         * ```typescript
         * const { isSignerInitialized } = useTransactionSigner();
         *
         * if (!isSignerInitialized) {
         *   return <LoadingSpinner text="Initializing signer..." />;
         * }
         * ```
         */
        isSignerInitialized,
        /**
         * Whether blockchain transaction signing is fully available
         *
         * This combines multiple checks: SDK availability, initialization status,
         * and configuration validity. Use this to enable/disable transaction buttons.
         *
         * Returns `true` only when:
         * - PERS Signer SDK is installed and available
         * - Signer has been successfully initialized
         * - All required dependencies are loaded
         *
         * @example
         * ```typescript
         * const { isSignerAvailable } = useTransactionSigner();
         *
         * return (
         *   <TouchableOpacity
         *     disabled={!isSignerAvailable}
         *     style={[styles.button, !isSignerAvailable && styles.disabled]}
         *   >
         *     <Text>{isSignerAvailable ? 'Sign Transaction' : 'Signer Unavailable'}</Text>
         *   </TouchableOpacity>
         * );
         * ```
         */
        isSignerAvailable: isSignerInitialized && !!getSignerSDKFactory(),
        /**
         * Current signing status for UI feedback
         *
         * Tracks the current state of the signing process. Use this to show
         * progress indicators or status messages during transaction signing.
         *
         * Possible values: 'initializing', 'authenticating', 'preparing',
         * 'signing', 'submitting', 'completed', 'error', 'expired'
         *
         * @example
         * ```typescript
         * const { currentStatus, statusMessage } = useTransactionSigner();
         *
         * return (
         *   <View>
         *     {currentStatus && (
         *       <Text>Status: {statusMessage}</Text>
         *     )}
         *   </View>
         * );
         * ```
         */
        currentStatus,
        /**
         * Human-readable status message
         *
         * Provides a user-friendly description of the current signing status.
         * Updates in real-time as the transaction progresses.
         */
        statusMessage,
    };
};
