<script setup lang="ts">
const { g, l, p } = useContentInjected()

const props = withDefaults(
  defineProps<{
    class?: string
    ux?: any
    buttonsProps?: any
    sendProps?: any
    privacyProps?: any
  }>(),
  {
    buttonsProps: { align: 'left' },
    sendProps: {
      color: 'primary',
      variant: 'solid',
      trailing: true,
    },
    privacyProps: {
      color: 'secondary',
      variant: 'outline',
      trailing: true,
    },
  }
)

import * as v from 'valibot'

const schema = computed(() =>
  v.object({
    name: v.pipe(v.string(), v.minLength(2, l.value.name.invalid)),
    email: v.pipe(v.string(), v.email(l.value.email.invalid)),
    subject: v.pipe(v.string(), v.minLength(3, l.value.subject.invalid)),
    message: v.pipe(v.string(), v.minLength(10, l.value.message.invalid)),
  })
)

const state = reactive({
  name: '',
  email: '',
  subject: '',
  message: '',
})

const toast = useToast()
const sending = ref(false)

async function onSubmit(event: any) {
  sending.value = true

  const start = Date.now()
  let success = false
  let attempt = 0

  while (true) {
    attempt += 1

    try {
      await $fetch('https://api.dominikmilacher.com/contact', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: {
          ...event.data,
          hotel: g.value.business.uid ?? '',
        },
      })

      success = true
      break
    } catch (error: any) {
      console.warn(`Send failed: ${JSON.stringify(error)}`)

      if (attempt >= 3) {
        break
      }
    }
  }

  const minimum = 2000
  const elapsed = Date.now() - start
  if (elapsed < minimum) {
    await new Promise((resolve) => setTimeout(resolve, minimum - elapsed))
  }

  toast.add({
    title: success ? l.value.sent.title : l.value.error.title,
    description: success ? l.value.sent.description : l.value.error.description,
    color: success ? 'success' : 'error',
  })

  if (success) {
    Object.assign(state, { name: '', email: '', subject: '', message: '' })
  }

  sending.value = false
}

const classes = useStyling(
  'contactForm',
  {
    slots: {
      base: 'flex flex-col',
      field: '[&>*]:m-0',
      input: 'w-full',
      send: 'cursor-pointer',
      privacy: '',
    },
  },
  props
)
</script>

<template>
  <UForm :class="classes.base" :state="state" :schema="schema" @submit="onSubmit">
    <UFormField name="name" :class="classes.field" :label="l.name.label" :ui="{ label: 'sr-only' }">
      <UInput v-model="state.name" :class="classes.input" :placeholder="l.name.prompt" />
    </UFormField>

    <UFormField
      name="email"
      :class="classes.field"
      :label="l.email.label"
      :ui="{ label: 'sr-only' }"
    >
      <UInput v-model="state.email" :class="classes.input" :placeholder="l.email.prompt" />
    </UFormField>

    <UFormField
      name="subject"
      :class="classes.field"
      :label="l.subject.label"
      :ui="{ label: 'sr-only' }"
    >
      <UInput v-model="state.subject" :class="classes.input" :placeholder="l.subject.prompt" />
    </UFormField>

    <UFormField
      name="message"
      :class="classes.field"
      :label="l.message.label"
      :ui="{ label: 'sr-only' }"
    >
      <UTextarea
        v-model="state.message"
        :rows="6"
        :class="classes.input"
        :placeholder="l.message.prompt"
      />
    </UFormField>

    <XContainerButtons v-bind="props.buttonsProps" class="fmt-1">
      <UButton
        type="submit"
        :class="classes.send"
        :icon="l.send.icon"
        :loading="sending"
        :loading-icon="l.send.sending"
        v-bind="props.sendProps"
      >
        {{ l.send.label }}
      </UButton>

      <UButton
        :class="classes.privacy"
        :icon="l.privacy.icon"
        :to="p(l.privacy.link)"
        v-bind="props.privacyProps"
      >
        {{ l.privacy.label }}
      </UButton>
    </XContainerButtons>
  </UForm>
</template>
