"use strict";

/**
 * OxyAuthScreen - Sign in with Oxy
 * 
 * This screen is used by OTHER apps in the Oxy ecosystem to authenticate users.
 * It presents two options:
 * 1. Scan QR code with Oxy Accounts app
 * 2. Open Oxy Accounts app directly (via deep link)
 * 
 * Uses WebSocket for real-time authorization updates (with polling fallback).
 * The Oxy Accounts app is where users manage their cryptographic identity.
 * This screen should NOT be used within the Accounts app itself.
 */

import { useState, useEffect, useCallback, useRef } from 'react';
import { View, Text, TouchableOpacity, StyleSheet, Linking, Platform, ActivityIndicator } from 'react-native';
import io from 'socket.io-client';
import { useThemeColors } from '../styles';
import { useOxy } from '../context/OxyContext';
import QRCode from 'react-native-qrcode-svg';
import OxyLogo from '../components/OxyLogo';

// Deep link scheme for Oxy Accounts app
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
const OXY_ACCOUNTS_SCHEME = 'oxyaccounts://';
const OXY_ACCOUNTS_WEB_URL = 'https://accounts.oxy.so';

// Auth session expiration (5 minutes)
const AUTH_SESSION_EXPIRY_MS = 5 * 60 * 1000;

// Polling interval (fallback if socket fails)
const POLLING_INTERVAL_MS = 3000;
const OxyAuthScreen = ({
  navigate,
  goBack,
  onAuthenticated,
  theme
}) => {
  const themeValue = theme === 'light' || theme === 'dark' ? theme : 'light';
  const colors = useThemeColors(themeValue);
  const {
    oxyServices,
    signIn,
    switchSession
  } = useOxy();
  const [authSession, setAuthSession] = useState(null);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState(null);
  const [isWaiting, setIsWaiting] = useState(false);
  const [connectionType, setConnectionType] = useState('socket');
  const socketRef = useRef(null);
  const pollingIntervalRef = useRef(null);
  const isProcessingRef = useRef(false);

  // Handle successful authorization
  const handleAuthSuccess = useCallback(async sessionId => {
    if (isProcessingRef.current) return;
    isProcessingRef.current = true;
    try {
      // Switch to the new session (this will get token, user data, and update state)
      if (switchSession) {
        const user = await switchSession(sessionId);
        if (onAuthenticated) {
          onAuthenticated(user);
        }
      } else {
        // Fallback if switchSession not available (shouldn't happen, but for safety)
        await oxyServices.getTokenBySession(sessionId);
        const user = await oxyServices.getUserBySession(sessionId);
        if (onAuthenticated) {
          onAuthenticated(user);
        }
      }
    } catch (err) {
      if (__DEV__) {
        console.error('Error completing auth:', err);
      }
      setError('Authorization successful but failed to complete sign in. Please try again.');
      isProcessingRef.current = false;
    }
  }, [oxyServices, switchSession, onAuthenticated]);

  // Connect to socket for real-time updates
  const connectSocket = useCallback(sessionToken => {
    const baseURL = oxyServices.getBaseURL();

    // Connect to the auth-session namespace (no authentication required)
    const socket = io(`${baseURL}/auth-session`, {
      transports: ['websocket', 'polling'],
      reconnection: true,
      reconnectionAttempts: 3,
      reconnectionDelay: 1000
    });
    socketRef.current = socket;
    socket.on('connect', () => {
      if (__DEV__) {
        console.log('Auth socket connected');
      }
      // Join the room for this session token
      socket.emit('join', sessionToken);
      setConnectionType('socket');
    });
    socket.on('joined', () => {
      if (__DEV__) {
        console.log('Joined auth session room');
      }
    });
    socket.on('auth_update', payload => {
      if (__DEV__) {
        console.log('Auth update received:', payload);
      }
      if (payload.status === 'authorized' && payload.sessionId) {
        cleanup();
        handleAuthSuccess(payload.sessionId);
      } else if (payload.status === 'cancelled') {
        cleanup();
        setError('Authorization was denied.');
      } else if (payload.status === 'expired') {
        cleanup();
        setError('Session expired. Please try again.');
      }
    });
    socket.on('connect_error', err => {
      if (__DEV__) {
        console.log('Socket connection error, falling back to polling:', err.message);
      }
      // Fall back to polling if socket fails
      socket.disconnect();
      startPolling(sessionToken);
    });
    socket.on('disconnect', () => {
      if (__DEV__) {
        console.log('Auth socket disconnected');
      }
    });
  }, [oxyServices, handleAuthSuccess]);

  // Start polling for authorization (fallback)
  const startPolling = useCallback(sessionToken => {
    setConnectionType('polling');
    pollingIntervalRef.current = setInterval(async () => {
      if (isProcessingRef.current) return;
      try {
        const response = await oxyServices.makeRequest('GET', `/api/auth/session/status/${sessionToken}`, undefined, {
          cache: false
        });
        if (response.authorized && response.sessionId) {
          cleanup();
          handleAuthSuccess(response.sessionId);
        } else if (response.status === 'cancelled') {
          cleanup();
          setError('Authorization was denied.');
        } else if (response.status === 'expired') {
          cleanup();
          setError('Session expired. Please try again.');
        }
      } catch (err) {
        // Silent fail for polling - will retry
        if (__DEV__) {
          console.log('Auth polling error:', err);
        }
      }
    }, POLLING_INTERVAL_MS);
  }, [oxyServices, handleAuthSuccess]);

  // Cleanup socket and polling
  const cleanup = useCallback(() => {
    setIsWaiting(false);
    if (socketRef.current) {
      socketRef.current.disconnect();
      socketRef.current = null;
    }
    if (pollingIntervalRef.current) {
      clearInterval(pollingIntervalRef.current);
      pollingIntervalRef.current = null;
    }
  }, []);

  // Generate a new auth session
  const generateAuthSession = useCallback(async () => {
    setIsLoading(true);
    setError(null);
    isProcessingRef.current = false;
    try {
      // Generate a unique session token for this auth request
      const sessionToken = generateSessionToken();
      const expiresAt = Date.now() + AUTH_SESSION_EXPIRY_MS;

      // Register the auth session with the server
      await oxyServices.makeRequest('POST', '/api/auth/session/create', {
        sessionToken,
        expiresAt,
        appId: Platform.OS // Identifier for requesting app
      }, {
        cache: false
      });
      setAuthSession({
        sessionToken,
        expiresAt
      });
      setIsWaiting(true);

      // Try socket first, will fall back to polling if needed
      connectSocket(sessionToken);
    } catch (err) {
      setError(err.message || 'Failed to create auth session');
    } finally {
      setIsLoading(false);
    }
  }, [oxyServices, connectSocket]);

  // Generate a random session token
  const generateSessionToken = () => {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < 32; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  };

  // Clean up on unmount
  useEffect(() => {
    return () => {
      cleanup();
    };
  }, [cleanup]);

  // Initialize auth session
  useEffect(() => {
    generateAuthSession();
  }, []);

  // Check if session expired
  useEffect(() => {
    if (authSession && Date.now() > authSession.expiresAt) {
      cleanup();
      setAuthSession(null);
      setError('Session expired. Please try again.');
    }
  }, [authSession, cleanup]);

  // Build the QR code data
  const getQRData = () => {
    if (!authSession) return '';

    // Format: oxyauth://{sessionToken}
    return `oxyauth://${authSession.sessionToken}`;
  };

  // Open Oxy Accounts app
  const handleOpenAccounts = useCallback(async () => {
    if (!authSession) return;
    const deepLinkUrl = `${OXY_ACCOUNTS_SCHEME}authorize?token=${authSession.sessionToken}`;
    const webUrl = `${OXY_ACCOUNTS_WEB_URL}/authorize?token=${authSession.sessionToken}`;
    try {
      const canOpen = await Linking.canOpenURL(deepLinkUrl);
      if (canOpen) {
        await Linking.openURL(deepLinkUrl);
      } else {
        // Fallback to web URL
        await Linking.openURL(webUrl);
      }
    } catch (err) {
      // Fallback to web URL
      try {
        await Linking.openURL(webUrl);
      } catch {
        setError('Unable to open Oxy Accounts. Please install the app or use QR code.');
      }
    }
  }, [authSession]);

  // Refresh session
  const handleRefresh = useCallback(() => {
    cleanup();
    generateAuthSession();
  }, [generateAuthSession, cleanup]);
  if (isLoading) {
    return /*#__PURE__*/_jsxs(View, {
      style: [styles.container, {
        backgroundColor: colors.background
      }],
      children: [/*#__PURE__*/_jsx(ActivityIndicator, {
        size: "large",
        color: colors.primary
      }), /*#__PURE__*/_jsx(Text, {
        style: [styles.loadingText, {
          color: colors.secondaryText
        }],
        children: "Preparing sign in..."
      })]
    });
  }
  if (error) {
    return /*#__PURE__*/_jsxs(View, {
      style: [styles.container, {
        backgroundColor: colors.background
      }],
      children: [/*#__PURE__*/_jsx(Text, {
        style: [styles.errorText, {
          color: colors.error
        }],
        children: error
      }), /*#__PURE__*/_jsx(TouchableOpacity, {
        style: [styles.button, {
          backgroundColor: colors.primary
        }],
        onPress: handleRefresh,
        children: /*#__PURE__*/_jsx(Text, {
          style: styles.buttonText,
          children: "Try Again"
        })
      })]
    });
  }
  return /*#__PURE__*/_jsxs(View, {
    style: [styles.container, {
      backgroundColor: colors.background
    }],
    children: [/*#__PURE__*/_jsxs(View, {
      style: styles.header,
      children: [/*#__PURE__*/_jsx(OxyLogo, {
        width: 48,
        height: 48
      }), /*#__PURE__*/_jsx(Text, {
        style: [styles.title, {
          color: colors.text
        }],
        children: "Sign in with Oxy"
      }), /*#__PURE__*/_jsx(Text, {
        style: [styles.subtitle, {
          color: colors.secondaryText
        }],
        children: "Use your Oxy identity to sign in securely"
      })]
    }), /*#__PURE__*/_jsxs(View, {
      style: [styles.qrContainer, {
        backgroundColor: colors.inputBackground,
        borderColor: colors.border
      }],
      children: [/*#__PURE__*/_jsx(View, {
        style: styles.qrWrapper,
        children: /*#__PURE__*/_jsx(QRCode, {
          value: getQRData(),
          size: 200,
          backgroundColor: "white",
          color: "black"
        })
      }), /*#__PURE__*/_jsx(Text, {
        style: [styles.qrHint, {
          color: colors.secondaryText
        }],
        children: "Scan with Oxy Accounts app"
      })]
    }), Platform.OS !== 'web' && /*#__PURE__*/_jsxs(_Fragment, {
      children: [/*#__PURE__*/_jsxs(View, {
        style: styles.dividerContainer,
        children: [/*#__PURE__*/_jsx(View, {
          style: [styles.divider, {
            backgroundColor: colors.border
          }]
        }), /*#__PURE__*/_jsx(Text, {
          style: [styles.dividerText, {
            color: colors.secondaryText
          }],
          children: "or"
        }), /*#__PURE__*/_jsx(View, {
          style: [styles.divider, {
            backgroundColor: colors.border
          }]
        })]
      }), /*#__PURE__*/_jsxs(TouchableOpacity, {
        style: [styles.button, {
          backgroundColor: colors.primary
        }],
        onPress: handleOpenAccounts,
        children: [/*#__PURE__*/_jsx(OxyLogo, {
          width: 20,
          height: 20,
          fillColor: "white",
          style: styles.buttonIcon
        }), /*#__PURE__*/_jsx(Text, {
          style: styles.buttonText,
          children: "Open Oxy Accounts"
        })]
      })]
    }), isWaiting && /*#__PURE__*/_jsxs(View, {
      style: styles.statusContainer,
      children: [/*#__PURE__*/_jsx(ActivityIndicator, {
        size: "small",
        color: colors.primary
      }), /*#__PURE__*/_jsx(Text, {
        style: [styles.statusText, {
          color: colors.secondaryText
        }],
        children: "Waiting for authorization..."
      })]
    }), /*#__PURE__*/_jsxs(View, {
      style: styles.footer,
      children: [/*#__PURE__*/_jsxs(Text, {
        style: [styles.footerText, {
          color: colors.secondaryText
        }],
        children: ["Don't have Oxy Accounts?", ' ']
      }), /*#__PURE__*/_jsx(TouchableOpacity, {
        onPress: () => Linking.openURL(OXY_ACCOUNTS_WEB_URL),
        children: /*#__PURE__*/_jsx(Text, {
          style: [styles.footerLink, {
            color: colors.primary
          }],
          children: "Get it here"
        })
      })]
    }), goBack && /*#__PURE__*/_jsx(TouchableOpacity, {
      style: styles.cancelButton,
      onPress: goBack,
      children: /*#__PURE__*/_jsx(Text, {
        style: [styles.cancelText, {
          color: colors.secondaryText
        }],
        children: "Cancel"
      })
    })]
  });
};
const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 24,
    alignItems: 'center',
    justifyContent: 'center'
  },
  header: {
    alignItems: 'center',
    marginBottom: 32
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginTop: 16
  },
  subtitle: {
    fontSize: 14,
    marginTop: 8,
    textAlign: 'center'
  },
  qrContainer: {
    padding: 24,
    borderRadius: 16,
    borderWidth: 1,
    alignItems: 'center'
  },
  qrWrapper: {
    padding: 16,
    backgroundColor: 'white',
    borderRadius: 12
  },
  qrHint: {
    marginTop: 16,
    fontSize: 12
  },
  dividerContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginVertical: 24,
    width: '100%'
  },
  divider: {
    flex: 1,
    height: 1
  },
  dividerText: {
    marginHorizontal: 16,
    fontSize: 14
  },
  button: {
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'center',
    paddingVertical: 16,
    paddingHorizontal: 24,
    borderRadius: 12,
    width: '100%'
  },
  buttonIcon: {
    marginRight: 10
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: '600'
  },
  statusContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    marginTop: 24
  },
  statusText: {
    marginLeft: 8,
    fontSize: 14
  },
  footer: {
    flexDirection: 'row',
    marginTop: 32
  },
  footerText: {
    fontSize: 14
  },
  footerLink: {
    fontSize: 14,
    fontWeight: '600'
  },
  cancelButton: {
    marginTop: 16,
    padding: 12
  },
  cancelText: {
    fontSize: 14
  },
  loadingText: {
    marginTop: 16,
    fontSize: 14
  },
  errorText: {
    fontSize: 14,
    textAlign: 'center',
    marginBottom: 16
  }
});
export default OxyAuthScreen;
//# sourceMappingURL=OxyAuthScreen.js.map