import React from 'react';
import * as AppleAuthentication from 'expo-apple-authentication';
import { StyleSheet, Alert } from 'react-native';
import { ThemedView } from '@/components/theme/Theme';
import { useColorScheme } from '@/hooks/useColorScheme';
import * as Notifications from 'expo-notifications';
import Constants from 'expo-constants';
import { saveUser, saveInitialData } from '@/components/services/SecureStore';
import {
  getInitialDataByAppleId,
  createUser,
  updatePushToken
} from '@/constants/APIs';
import type { InitialData, User } from '@/constants/Types';

const SignInScreen = ({onSignIn}: {onSignIn: () => void}) => {
  const scheme = useColorScheme() ?? 'dark';

  const handleAppleSignIn = async () => {
    try {
      const credential = await AppleAuthentication.signInAsync({
        requestedScopes: [
          AppleAuthentication.AppleAuthenticationScope.EMAIL,
          AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
        ],
      });
      const projectId = Constants.expoConfig?.extra?.eas?.projectId;
      if (!projectId) throw new Error('Project ID not found in eas.json');

      const pushToken = await Notifications.getExpoPushTokenAsync({
        projectId: projectId,
      });
      console.log(
        credential.user, credential.email, credential.fullName?.givenName,
        credential.fullName?.familyName, pushToken.data
      );

      const initialDataResponse = await getInitialDataByAppleId(credential.user);

      console.log(initialDataResponse);
      if (initialDataResponse.status === 404 || !initialDataResponse.ok) {
        if (!credential.user || !credential.email ||
            !credential.fullName?.givenName || !credential.fullName?.familyName ||
            !pushToken || credential.email.length === 0) {
          Alert.alert(
            'Sign in error',
            'Unable to create an account. ' + 
              'Remove App from Sign in with Apple & try again.',
          );
          throw new Error(
            'Incomplete user data. This shouldn\'t happen & means that user has ' +
              'previously signed in with Apple, but their user data did not ' +
              'save in the database.'
          );
        }
        const user: User = await createUser(
          credential.user,
          credential.email,
          credential.fullName?.givenName + ' ' + credential.fullName?.familyName,
          pushToken.data
        ) as User;
        await saveUser(user);
      } else if (initialDataResponse.ok) {
        const initialData: InitialData = await initialDataResponse.json() as InitialData;
        console.log('Existing user found! Saving data...');

        if (initialData.user.pushToken !== pushToken.data) {
          const updatePushTokenResponse = await updatePushToken(
            initialData.user.id,
            pushToken.data
          );
        } else {
          console.log('Push token is up to date.');
        }
        initialData.user.pushToken = pushToken.data;
        await saveInitialData(initialData);
      }
      onSignIn();
    } catch (error: unknown) {
      console.error('Error signing in:', error);
      if (error.code === 'ERR_REQUEST_CANCELLED') {
        Alert.alert('Sign in error', 'Sign in was cancelled.');
      } else {
        Alert.alert(
          'Sign in error',
          'An error occurred while signing in. Please try again or contact support.'
        );
      }
    }
  };

  return (
    <ThemedView style={styles.container}>
      <AppleAuthentication.AppleAuthenticationButton
        buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
        buttonStyle={(scheme === 'light') ?
          AppleAuthentication.AppleAuthenticationButtonStyle.BLACK :
          AppleAuthentication.AppleAuthenticationButtonStyle.WHITE
        }
        cornerRadius={5}
        style={styles.button}
        onPress={handleAppleSignIn}
      />
    </ThemedView>
  );
};
export default SignInScreen;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  button: {
    width: 200,
    height: 45,
  },
});
