import * as Linking from 'expo-linking'
import { useLocalSearchParams, useRouter } from 'expo-router'
import * as WebBrowser from 'expo-web-browser'
import InAppBrowser from 'react-native-inappbrowser-reborn'
import { SafeAreaView } from 'react-native-safe-area-context'
import { useStyles } from 'react-native-unistyles'
import useSWR from 'swr'

import { getSession, saveSessionToUserTable } from '~/api/session'
import { Column, Container, Text, TextButton } from '~/components'
import { Image } from '~/components/image'
import { commonStylesheet } from '~/theme/common'

function obtainAuthToken() {
  return new Promise<string>((resolve) => {
    const subscription = Linking.addEventListener('url', ({ url }) => {
      const { hostname, queryParams } = Linking.parse(url)
      if (hostname === 'auth' && queryParams !== null && typeof queryParams.ck === 'string') {
        WebBrowser.dismissBrowser()
          .catch(console.error)
        InAppBrowser.close()
        const { ck } = queryParams
        resolve(ck)
        subscription.remove()
      }
    })

    InAppBrowser.isAvailable()
      .then((isAvailable) => {
        if (!isAvailable) {
          WebBrowser.openBrowserAsync(process.env.EXPO_PUBLIC_FOLLOW_LOGIN_URL)
            .catch(console.error)
        }
        InAppBrowser.open(process.env.EXPO_PUBLIC_FOLLOW_LOGIN_URL)
          .catch(console.error)
      })
      .catch(console.error)
  })
}

export default function Auth() {
  const router = useRouter()
  const searchParams = useLocalSearchParams()
  const { isLoading } = useSWR<void, Error, ['sign-in', string | string[] | null]>(
    ['sign-in', searchParams?.ck ?? null],
    ([_, ck]) => {
      if (!ck || Array.isArray(ck))
        throw new Error('has not token')

      const cookie = atob(ck)
      const token = cookie.split('=')[1]!

      return new Promise((resolve, reject) => {
        getSession(token)
          .then((session) => {
            saveSessionToUserTable(token, session)
              .then(() => {
                resolve()
              })
              .catch(() => {
                reject(new Error('Failed to save session'))
              })
          })
          .catch(() => {
            reject(new Error('Failed to get session'))
          })
      })
    },
    {
      onSuccess() {
        router.replace('/')
      },
    },
  )

  const { styles } = useStyles(commonStylesheet)
  return (
    <SafeAreaView style={styles.appBackground}>
      <Container align="center" px={20}>
        <Column flex={1} justify="center">
          <Image
            source={require('~/assets/icon.png')}
            style={{
              width: 80,
              height: 80,
              borderRadius: 20,
            }}
          />
        </Column>
        <Column w="100%" gap={8} flex={1} pt={60}>
          <TextButton
            color="accent"
            variant="solid"
            radius="full"
            style={{ width: '100%' }}
            onPress={async () => {
              await obtainAuthToken()
            }}
            disabled={isLoading}
            isLoading={isLoading}
            title="Sign in"
          />
          <Text size={14} style={{ textAlign: 'center' }}>
            Use your personal account to sign in on web.follow.is
          </Text>
        </Column>
      </Container>
    </SafeAreaView>
  )
}
