import React, { useRef, useState, useCallback } from 'react';
import {
  View,
  StyleSheet,
  ActivityIndicator,
  Text,
  TouchableOpacity,
  BackHandler,
  Platform,
  Alert,
} from 'react-native';
import * as Location from 'expo-location';
import { WebView, WebViewMessageEvent } from 'react-native-webview';
import { useFocusEffect, useNavigation } from '@react-navigation/native';
import type { NavigationProp } from '@react-navigation/native';
import { KurdistanColors } from '../theme/colors';
import { usePezkuwi } from '../contexts/PezkuwiContext';
import { useAuth } from '../contexts/AuthContext';
import { supabase } from '../lib/supabase';

type RootStackParamList = {
  Wallet: undefined;
  WalletSetup: undefined;
};

// Base URL for the web app
const WEB_BASE_URL = 'https://pezkuwichain.io';

export interface PezkuwiWebViewProps {
  // The path to load (e.g., '/p2p', '/forum', '/elections')
  path: string;
  // Optional title for the header
  title?: string;
  // Callback when navigation state changes
  onNavigationStateChange?: (canGoBack: boolean) => void;
}

interface WebViewMessage {
  type: string;
  payload?: unknown;
}

const PezkuwiWebView: React.FC<PezkuwiWebViewProps> = ({
  path,
  title,
  onNavigationStateChange,
}) => {
  const webViewRef = useRef<WebView>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [canGoBack, setCanGoBack] = useState(false);

  const navigation = useNavigation<NavigationProp<RootStackParamList>>();
  const { selectedAccount, getKeyPair, api, isApiReady } = usePezkuwi();
  const { user } = useAuth();
  const [sessionToken, setSessionToken] = useState<string | null>(null);
  const [refreshToken, setRefreshToken] = useState<string | null>(null);
  const [isSessionReady, setIsSessionReady] = useState(false);

  // Get Supabase session token for WebView authentication
  React.useEffect(() => {
    const getSession = async () => {
      try {
        const { data: { session } } = await supabase.auth.getSession();
        if (session?.access_token) {
          setSessionToken(session.access_token);
          setRefreshToken(session.refresh_token || null);
          if (__DEV__) console.warn('[WebView] Session token retrieved for SSO');
        }
      } catch (error) {
        if (__DEV__) console.warn('[WebView] Failed to get session:', error);
      } finally {
        setIsSessionReady(true);
      }
    };
    getSession();
  }, [user]);

  // Runs BEFORE any page JS — sets the mobile flag and overrides geolocation
  // so React's useEffect sees them on first render
  const injectedJavaScriptBeforeContentLoaded = `
    (function() {
      window.PEZKUWI_MOBILE = true;
      window.PEZKUWI_PLATFORM = '${Platform.OS}';

      // Override navigator.geolocation before React mounts
      var _pendingLocationCallbacks = {};
      var _locationCallbackId = 0;

      var _overrideGeo = {
        getCurrentPosition: function(success, error, options) {
          var id = ++_locationCallbackId;
          _pendingLocationCallbacks[id] = { success: success, error: error };
          window.ReactNativeWebView.postMessage(JSON.stringify({
            type: 'REQUEST_LOCATION',
            payload: { id: id }
          }));
          setTimeout(function() {
            if (_pendingLocationCallbacks[id]) {
              delete _pendingLocationCallbacks[id];
              if (error) error({ code: 3, message: 'Timeout' });
            }
          }, 15000);
        },
        watchPosition: function() { return 0; },
        clearWatch: function() {}
      };

      try {
        Object.defineProperty(navigator, 'geolocation', {
          get: function() { return _overrideGeo; },
          configurable: true
        });
      } catch(e) {}

      window.__resolveLocation = function(id, lat, lon, accuracy) {
        var cb = _pendingLocationCallbacks[id];
        if (cb) {
          delete _pendingLocationCallbacks[id];
          cb.success({ coords: { latitude: lat, longitude: lon, accuracy: accuracy || 50, altitude: null, altitudeAccuracy: null, heading: null, speed: null }, timestamp: Date.now() });
        }
      };

      window.__rejectLocation = function(id, code, msg) {
        var cb = _pendingLocationCallbacks[id];
        if (cb) {
          delete _pendingLocationCallbacks[id];
          if (cb.error) cb.error({ code: code || 1, message: msg || 'Permission denied' });
        }
      };

      true;
    })();
  `;

  // JavaScript to inject into the WebView
  // This creates a bridge between the web app and native app
  const injectedJavaScript = `
    (function() {

      // Inject wallet address if connected
      ${selectedAccount ? `window.PEZKUWI_ADDRESS = '${selectedAccount.address}';` : ''}
      ${selectedAccount ? `window.PEZKUWI_ACCOUNT_NAME = '${selectedAccount.meta?.name || 'Mobile Wallet'}';` : ''}

      // Inject auth session for automatic login
      ${sessionToken ? `window.PEZKUWI_SESSION_TOKEN = '${sessionToken}';` : ''}
      ${refreshToken ? `window.PEZKUWI_REFRESH_TOKEN = '${refreshToken}';` : ''}
      ${user ? `window.PEZKUWI_USER_ID = '${user.id}';` : ''}
      ${user?.email ? `window.PEZKUWI_USER_EMAIL = '${user.email}';` : ''}

      // Pre-populate localStorage with session so Supabase client finds it on init
      ${sessionToken && user ? `
      try {
        var supabaseUrl = 'https://sihawipngjtgvfzukfew.supabase.co';
        var storageKey = 'sb-' + supabaseUrl.replace('https://', '').split('.')[0] + '-auth-token';
        var sessionData = {
          access_token: '${sessionToken}',
          refresh_token: '${refreshToken || ''}',
          token_type: 'bearer',
          expires_in: 3600,
          expires_at: Math.floor(Date.now() / 1000) + 3600,
          user: {
            id: '${user.id}',
            email: '${user.email || ''}',
            aud: 'authenticated',
            role: 'authenticated'
          }
        };
        localStorage.setItem(storageKey, JSON.stringify(sessionData));
        console.log('[Mobile] Pre-populated localStorage with session');
      } catch(e) {
        console.warn('[Mobile] Failed to set localStorage:', e);
      }
      ` : ''}

      // Auto-authenticate with Supabase if session token exists
      if (window.PEZKUWI_SESSION_TOKEN) {
        (function autoAuth(attempts = 0) {
          if (attempts > 50) {
            console.warn('[Mobile] Auto-auth timed out: window.supabase not found');
            return;
          }

          if (window.supabase && window.supabase.auth) {
            window.supabase.auth.setSession({
              access_token: window.PEZKUWI_SESSION_TOKEN,
              refresh_token: window.PEZKUWI_REFRESH_TOKEN || ''
            }).then(function(res) {
              if (res.error) {
                console.warn('[Mobile] Auto-auth error:', res.error);
              } else {
                console.log('[Mobile] Auto-authenticated successfully');
                // Dispatch event to notify app of successful auth
                window.dispatchEvent(new CustomEvent('pezkuwi-session-restored', {
                  detail: { userId: window.PEZKUWI_USER_ID }
                }));
                // Force auth state refresh if the app has an auth store
                if (window.__refreshAuthState) {
                  window.__refreshAuthState();
                }
              }
            }).catch(function(err) {
              console.warn('[Mobile] Auto-auth promise failed:', err);
            });
          } else {
            setTimeout(function() { autoAuth(attempts + 1); }, 100);
          }
        })(0);
      }

      // Override console.log to send to React Native (for debugging)
      const originalConsoleLog = console.log;
      console.log = function(...args) {
        originalConsoleLog.apply(console, args);
        window.ReactNativeWebView?.postMessage(JSON.stringify({
          type: 'CONSOLE_LOG',
          payload: args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ')
        }));
      };

      // Create native bridge for wallet operations
      window.PezkuwiNativeBridge = {
        // Request transaction signing and submission from native wallet
        signTransaction: function(payload, callback) {
          window.__pendingSignCallback = callback;
          window.ReactNativeWebView?.postMessage(JSON.stringify({
            type: 'SIGN_TRANSACTION',
            payload: payload
          }));
        },

        // Request wallet connection
        connectWallet: function() {
          window.ReactNativeWebView?.postMessage(JSON.stringify({
            type: 'CONNECT_WALLET'
          }));
        },

        // Navigate back in native app
        goBack: function() {
          window.ReactNativeWebView?.postMessage(JSON.stringify({
            type: 'GO_BACK'
          }));
        },

        // Check if wallet is connected
        isWalletConnected: function() {
          return !!window.PEZKUWI_ADDRESS;
        },

        // Get connected address
        getAddress: function() {
          return window.PEZKUWI_ADDRESS || null;
        }
      };

      // Notify web app that native bridge is ready
      window.dispatchEvent(new CustomEvent('pezkuwi-native-ready', {
        detail: {
          address: window.PEZKUWI_ADDRESS,
          platform: window.PEZKUWI_PLATFORM
        }
      }));

      true; // Required for injectedJavaScript
    })();
  `;

  // Handle messages from WebView
  const handleMessage = useCallback(async (event: WebViewMessageEvent) => {
    try {
      const message: WebViewMessage = JSON.parse(event.nativeEvent.data);

      switch (message.type) {
        case 'SIGN_TRANSACTION':
          // Handle transaction signing and submission
          if (!selectedAccount) {
            webViewRef.current?.injectJavaScript(`
              if (window.__pendingSignCallback) {
                window.__pendingSignCallback(null, 'Wallet not connected');
                delete window.__pendingSignCallback;
              }
            `);
            return;
          }

          if (!api || !isApiReady) {
            webViewRef.current?.injectJavaScript(`
              if (window.__pendingSignCallback) {
                window.__pendingSignCallback(null, 'Blockchain not connected');
                delete window.__pendingSignCallback;
              }
            `);
            return;
          }

          try {
            const payload = message.payload as {
              section: string;
              method: string;
              args: unknown[];
            };

            const keyPair = await getKeyPair(selectedAccount.address);
            if (!keyPair) {
              throw new Error('Could not retrieve key pair');
            }

            // Build the transaction using native API
            const { section, method, args } = payload;

            if (__DEV__) {
              console.warn('[WebView] Building transaction:', { section, method, args });
            }

            // Get the transaction method from API
            const txModule = api.tx[section] as Record<string, (...args: unknown[]) => { signAndSend: (...args: unknown[]) => Promise<unknown> }> | undefined;
            if (!txModule) {
              throw new Error(`Unknown section: ${section}`);
            }

            const txMethod = txModule[method];
            if (!txMethod) {
              throw new Error(`Unknown method: ${section}.${method}`);
            }

            // Create the transaction
            const tx = txMethod(...args);

            // Sign and send transaction
            const txHash = await new Promise<string>((resolve, reject) => {
              tx.signAndSend(keyPair, { nonce: -1 }, (result: { status: { isInBlock?: boolean; isFinalized?: boolean; asInBlock?: { toString: () => string }; asFinalized?: { toString: () => string } }; dispatchError?: unknown }) => {
                if (result.status.isInBlock) {
                  const hash = result.status.asInBlock?.toString() || '';
                  if (__DEV__) {
                    console.warn('[WebView] Transaction included in block:', hash);
                  }
                  resolve(hash);
                } else if (result.status.isFinalized) {
                  const hash = result.status.asFinalized?.toString() || '';
                  if (__DEV__) {
                    console.warn('[WebView] Transaction finalized:', hash);
                  }
                }
                if (result.dispatchError) {
                  reject(new Error('Transaction failed'));
                }
              }).catch(reject);
            });

            // Send success back to WebView
            webViewRef.current?.injectJavaScript(`
              if (window.__pendingSignCallback) {
                window.__pendingSignCallback('${txHash}', null);
                delete window.__pendingSignCallback;
              }
            `);
          } catch (signError) {
            const errorMessage = (signError as Error).message.replace(/'/g, "\\'");
            webViewRef.current?.injectJavaScript(`
              if (window.__pendingSignCallback) {
                window.__pendingSignCallback(null, '${errorMessage}');
                delete window.__pendingSignCallback;
              }
            `);
          }
          break;

        case 'CONNECT_WALLET':
          // Handle wallet connection request from WebView
          if (__DEV__) console.warn('WebView requested wallet connection');

          if (selectedAccount) {
            // Already connected, notify WebView
            webViewRef.current?.injectJavaScript(`
              window.PEZKUWI_ADDRESS = '${selectedAccount.address}';
              window.PEZKUWI_ACCOUNT_NAME = '${selectedAccount.meta?.name || 'Mobile Wallet'}';
              window.dispatchEvent(new CustomEvent('pezkuwi-wallet-connected', {
                detail: {
                  address: '${selectedAccount.address}',
                  name: '${selectedAccount.meta?.name || 'Mobile Wallet'}'
                }
              }));
            `);
          } else {
            // No wallet connected, show alert and navigate to wallet setup
            Alert.alert(
              'Wallet Required',
              'Please connect or create a wallet to continue.',
              [
                {
                  text: 'Cancel',
                  style: 'cancel',
                },
                {
                  text: 'Setup Wallet',
                  onPress: () => {
                    navigation.navigate('WalletSetup');
                  },
                },
              ]
            );
          }
          break;

        case 'REQUEST_LOCATION': {
          const locId = (message.payload as { id: number }).id;
          try {
            const { status } = await Location.requestForegroundPermissionsAsync();
            if (status !== 'granted') {
              webViewRef.current?.injectJavaScript(
                `window.__rejectLocation(${locId}, 1, 'Permission denied'); true;`
              );
              break;
            }
            const pos = await Location.getCurrentPositionAsync({
              accuracy: Location.Accuracy.Balanced,
            });
            webViewRef.current?.injectJavaScript(
              `window.__resolveLocation(${locId}, ${pos.coords.latitude}, ${pos.coords.longitude}, ${pos.coords.accuracy}); true;`
            );
          } catch (locErr) {
            webViewRef.current?.injectJavaScript(
              `window.__rejectLocation(${locId}, 2, 'Location unavailable'); true;`
            );
          }
          break;
        }

        case 'GO_BACK':
          // Handle back navigation from web
          if (canGoBack && webViewRef.current) {
            webViewRef.current.goBack();
          }
          break;

        case 'CONSOLE_LOG':
          // Forward console logs from WebView (debug only)
          if (__DEV__) {
            console.warn('[WebView]:', message.payload);
          }
          break;

        default:
          if (__DEV__) {
            console.warn('Unknown message type:', message.type);
          }
      }
    } catch (parseError) {
      if (__DEV__) {
        console.error('Failed to parse WebView message:', parseError);
      }
    }
  }, [selectedAccount, getKeyPair, canGoBack, navigation, api, isApiReady]);

  // Handle Android back button
  useFocusEffect(
    useCallback(() => {
      const onBackPress = () => {
        if (canGoBack && webViewRef.current) {
          webViewRef.current.goBack();
          return true; // Prevent default behavior
        }
        return false; // Allow default behavior
      };

      const subscription = BackHandler.addEventListener('hardwareBackPress', onBackPress);
      return () => subscription.remove();
    }, [canGoBack])
  );

  // Reload the WebView
  const handleReload = () => {
    setError(null);
    setLoading(true);
    webViewRef.current?.reload();
  };

  // Go back in WebView history
  const handleGoBack = () => {
    if (canGoBack && webViewRef.current) {
      webViewRef.current.goBack();
    }
  };

  // Build the full URL
  const fullUrl = `${WEB_BASE_URL}${path}`;

  // Wait for session to be ready before loading WebView (ensures SSO works)
  if (!isSessionReady) {
    return (
      <View style={styles.container}>
        {title && (
          <View style={styles.header}>
            <View style={{ width: 40 }} />
            <Text style={styles.headerTitle}>{title}</Text>
            <View style={{ width: 40 }} />
          </View>
        )}
        <View style={styles.loadingOverlay}>
          <ActivityIndicator size="large" color={KurdistanColors.kesk} />
          <Text style={styles.loadingText}>Preparing session...</Text>
        </View>
      </View>
    );
  }

  // Error view
  if (error) {
    return (
      <View style={styles.errorContainer}>
        <Text style={styles.errorIcon}>!</Text>
        <Text style={styles.errorTitle}>Connection Error</Text>
        <Text style={styles.errorMessage}>{error}</Text>
        <TouchableOpacity style={styles.retryButton} onPress={handleReload}>
          <Text style={styles.retryButtonText}>Try Again</Text>
        </TouchableOpacity>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      {/* Optional header with back button */}
      {title && (
        <View style={styles.header}>
          {canGoBack && (
            <TouchableOpacity style={styles.backButton} onPress={handleGoBack}>
              <Text style={styles.backButtonText}>{'<'}</Text>
            </TouchableOpacity>
          )}
          <Text style={styles.headerTitle}>{title}</Text>
          <TouchableOpacity style={styles.reloadButton} onPress={handleReload}>
            <Text style={styles.reloadButtonText}>Reload</Text>
          </TouchableOpacity>
        </View>
      )}

      {/* WebView */}
      <WebView
        ref={webViewRef}
        source={{ uri: fullUrl }}
        style={styles.webView}
        injectedJavaScriptBeforeContentLoaded={injectedJavaScriptBeforeContentLoaded}
        injectedJavaScript={injectedJavaScript}
        onMessage={handleMessage}
        onLoadStart={() => setLoading(true)}
        onLoadEnd={() => setLoading(false)}
        onError={(syntheticEvent) => {
          const { nativeEvent } = syntheticEvent;
          setError(nativeEvent.description || 'Failed to load page');
          setLoading(false);
        }}
        onHttpError={(syntheticEvent) => {
          const { nativeEvent } = syntheticEvent;
          if (nativeEvent.statusCode >= 400) {
            setError(`HTTP Error: ${nativeEvent.statusCode}`);
          }
        }}
        onNavigationStateChange={(navState) => {
          setCanGoBack(navState.canGoBack);
          onNavigationStateChange?.(navState.canGoBack);
        }}
        // Security settings
        javaScriptEnabled={true}
        domStorageEnabled={true}
        geolocationEnabled={true}
        sharedCookiesEnabled={true}
        thirdPartyCookiesEnabled={true}
        // Performance settings
        cacheEnabled={true}
        cacheMode="LOAD_DEFAULT"
        // UI settings
        showsHorizontalScrollIndicator={false}
        showsVerticalScrollIndicator={true}
        bounces={true}
        pullToRefreshEnabled={true}
        // Behavior settings
        allowsBackForwardNavigationGestures={true}
        allowsInlineMediaPlayback={true}
        mediaPlaybackRequiresUserAction={false}
        // Debugging (dev only)
        webviewDebuggingEnabled={__DEV__}
      />

      {/* Loading overlay */}
      {loading && (
        <View style={styles.loadingOverlay}>
          <ActivityIndicator size="large" color={KurdistanColors.kesk} />
          <Text style={styles.loadingText}>Loading...</Text>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FFFFFF',
  },
  header: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-between',
    paddingHorizontal: 16,
    paddingVertical: 12,
    backgroundColor: '#FFFFFF',
    borderBottomWidth: 1,
    borderBottomColor: '#E0E0E0',
  },
  headerTitle: {
    flex: 1,
    fontSize: 18,
    fontWeight: '700',
    color: '#000',
    textAlign: 'center',
  },
  backButton: {
    padding: 8,
    marginRight: 8,
  },
  backButtonText: {
    fontSize: 24,
    color: KurdistanColors.kesk,
    fontWeight: '600',
  },
  reloadButton: {
    padding: 8,
  },
  reloadButtonText: {
    fontSize: 14,
    color: KurdistanColors.kesk,
    fontWeight: '600',
  },
  webView: {
    flex: 1,
  },
  loadingOverlay: {
    ...StyleSheet.absoluteFillObject,
    backgroundColor: 'rgba(255, 255, 255, 0.9)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  loadingText: {
    marginTop: 12,
    fontSize: 14,
    color: '#666',
  },
  errorContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 32,
    backgroundColor: '#FFFFFF',
  },
  errorIcon: {
    fontSize: 48,
    color: KurdistanColors.sor,
    marginBottom: 16,
    fontWeight: '700',
  },
  errorTitle: {
    fontSize: 20,
    fontWeight: '700',
    color: '#000',
    marginBottom: 8,
  },
  errorMessage: {
    fontSize: 14,
    color: '#666',
    textAlign: 'center',
    marginBottom: 24,
  },
  retryButton: {
    backgroundColor: KurdistanColors.kesk,
    paddingHorizontal: 24,
    paddingVertical: 12,
    borderRadius: 8,
  },
  retryButtonText: {
    color: '#FFFFFF',
    fontSize: 16,
    fontWeight: '600',
  },
});

export default PezkuwiWebView;
