<script setup lang="ts">
import type { IAccountLoginResponse, IAccountProvider, IAccountProviderData } from '~/types/account'
import type { ButtonProps } from '#ui/components/Button.vue'

const config = useRuntimeConfig()
const router = useRouter()
const auth = useAuthStore()
const form = useTemplateRef('form')

const state = reactive({
  email: '',
  password: '',
  remember: false,
})

const { refresh: onSubmit, status: loginStatus } = useFetch<IAccountLoginResponse>('login', {
  method: 'POST',
  body: state,
  immediate: false,
  watch: false,
  async onResponse({ response }) {
    if (response?.status === 422) {
      form?.value?.setErrors(response._data?.errors)
    }
    else if (response._data?.ok) {
      auth.token = response._data.token

      await auth.fetchUser()
      await router.push('/')
    }
  },
})

const providers = ref<{ [key: string]: IAccountProvider }>(
  Object.fromEntries(
    Object.entries(config.public.providers).map(([key, provider]) => [
      key,
      {
        ...provider,
        color: provider.color as ButtonProps['color'],
      },
    ]),
  ),
)

async function handleMessage(event: { data: IAccountProviderData }): Promise<void> {
  const provider = event.data.provider as string

  if (Object.keys(providers.value).includes(provider) && event.data.token) {
    if (providers?.value[provider]?.loading) {
      providers.value[provider].loading = false
    }
    auth.token = event.data.token

    await auth.fetchUser()
    await router.push('/')
  }
  else if (event.data.message) {
    useToast().add({
      icon: 'i-heroicons-exclamation-circle-solid',
      color: 'error',
      title: event.data.message,
    })
  }
}

function loginVia(provider: string): void {
  providers.value[provider]!.loading = true

  const width = 640
  const height = 660
  const left = window.screen.width / 2 - width / 2
  const top = window.screen.height / 2 - height / 2

  const popup = window.open(
    `${config.public.apiBase}${config.public.apiPrefix}/login/${provider}/redirect`,
    'Sign In',
    `toolbar=no, location=no, directories=no, status=no, menubar=no, scollbars=no, resizable=no, copyhistory=no, width=${width},height=${height},top=${top},left=${left}`,
  )

  const interval = setInterval(() => {
    if (!popup || popup.closed) {
      clearInterval(interval)
      providers.value[provider]!.loading = false
    }
  }, 500)
}

onMounted(() => window.addEventListener('message', handleMessage))
onBeforeUnmount(() => window.removeEventListener('message', handleMessage))
</script>

<template>
  <UForm
    ref="form"
    :state="state"
    class="space-y-4"
    @submit="onSubmit"
  >
    <UFormField
      label="Email"
      name="email"
    >
      <UInput
        v-model="state.email"
        class="w-full"
      />
    </UFormField>

    <UFormField
      label="Password"
      name="password"
    >
      <UInput
        v-model="state.password"
        type="password"
        class="w-full"
      />
    </UFormField>

    <div class="flex items-center justify-between">
      <UCheckbox
        id="remember-me"
        v-model="state.remember"
        label="Remember me"
        name="remember-me"
      />

      <div class="text-sm leading-6">
        <NuxtLink
          to="/forgot-password"
          class="text-primary hover:text-primary-300 font-semibold"
        >
          Forgot
          password?
        </NuxtLink>
      </div>
    </div>

    <UButton
      block
      size="md"
      type="submit"
      :loading="loginStatus === 'pending'"
      icon="i-heroicons-arrow-right-on-rectangle"
    >
      Login
    </UButton>
  </UForm>
  <USeparator
    v-if="Object.keys(providers).length > 0"
    color="neutral"
    label="Login with"
    class="my-4"
  />
  <div class="flex gap-4">
    <UButton
      v-for="(provider, key) in providers"
      :key="key"
      :loading="provider.loading"
      :icon="provider.icon"
      :color="provider.color"
      :label="provider.name"
      size="lg"
      class="w-full flex items-center justify-center"
      @click="loginVia(key as string)"
    />
  </div>
</template>

<style scoped>

</style>
