import { useMemo, useState } from 'react';
import { Alert, Text, View } from 'react-native';
import * as Linking from 'expo-linking';
import * as WebBrowser from 'expo-web-browser';
import { useAuthActions } from '@convex-dev/auth/react';

import { AppScreen } from '~/components/ui/app-screen';
import { Button } from '~/components/ui/button';
import { Card } from '~/components/ui/card';
import { Field } from '~/components/ui/field';

WebBrowser.maybeCompleteAuthSession();

type OAuthProvider = 'github' | 'authentik';

export const SignInScreen = () => {
  const { signIn } = useAuthActions();
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [submitting, setSubmitting] = useState(false);
  const redirectTo = useMemo(() => Linking.createURL(''), []);

  const signInWithPassword = async () => {
    setSubmitting(true);
    try {
      await signIn('password', { email, password, flow: 'signIn' });
    } catch (error) {
      console.error(error);
      Alert.alert('Sign in failed', 'Check your email and password.');
    } finally {
      setSubmitting(false);
    }
  };

  const signInWithOAuth = async (provider: OAuthProvider) => {
    setSubmitting(true);
    try {
      const result = await signIn(provider, { redirectTo });
      if (!result.redirect) return;
      const authResult = await WebBrowser.openAuthSessionAsync(
        result.redirect.toString(),
        redirectTo,
      );
      if (authResult.type !== 'success') return;
      const parsed = Linking.parse(authResult.url);
      const code = parsed.queryParams?.code;
      if (typeof code !== 'string') {
        Alert.alert('Sign in failed', 'The provider did not return a code.');
        return;
      }
      await signIn(provider, { code });
    } catch (error) {
      console.error(error);
      Alert.alert('Sign in failed', `Could not complete ${provider} sign in.`);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <AppScreen>
      <View className='gap-2'>
        <Text className='text-foreground text-4xl font-bold'>Spoon</Text>
        <Text className='text-muted-foreground text-base leading-6'>
          Fork freely & keep them close to upstream.
        </Text>
      </View>

      <Card className='gap-3'>
        <Button
          disabled={submitting}
          onPress={() => void signInWithOAuth('github')}
        >
          Continue with GitHub
        </Button>
        <Button
          disabled={submitting}
          variant='outline'
          onPress={() => void signInWithOAuth('authentik')}
        >
          Continue with Authentik
        </Button>
      </Card>

      <Card className='gap-4'>
        <Text className='text-foreground font-semibold'>
          Sign in with email
        </Text>
        <Field
          keyboardType='email-address'
          label='Email'
          placeholder='you@example.com'
          value={email}
          onChangeText={setEmail}
        />
        <Field
          label='Password'
          placeholder='Password'
          secureTextEntry
          value={password}
          onChangeText={setPassword}
        />
        <Button disabled={submitting} onPress={() => void signInWithPassword()}>
          Sign in with email
        </Button>
      </Card>

      <Text className='text-muted-foreground text-sm leading-5'>
        Native OAuth callbacks should allow the `spoon://` redirect scheme.
      </Text>
    </AppScreen>
  );
};
