<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { IdentityBasic } from '@KTXM/MailManager/models/identity'
import { ServiceObject } from '@KTXM/MailManager/models/service'
import type { ServiceIdentity, ServiceIdentityBasic } from '@KTXM/MailManager/types/service'
import type { ProviderAuthPanelProps, ProviderAuthPanelEmits } from '@KTXM/MailManager/types/integration'

const props = defineProps<ProviderAuthPanelProps>()
const emit = defineEmits<ProviderAuthPanelEmits>()

const identity = ref('')
const secret = ref('')

const rules = {
  required: (value: unknown) => !!value || 'This field is required'
}

const currentIdentity = computed((): ServiceIdentityBasic | null => {
  if (!identity.value || !secret.value) {
    return null
  }

  return {
    type: 'BA',
    identity: identity.value,
    secret: secret.value,
  }
})

watch(
  () => props.service,
  service => {
    syncFromService(service)
  },
  { immediate: true }
)

watch(
  () => props.emailAddress,
  value => {
    if (value && !identity.value) {
      identity.value = value
    }
  },
  { immediate: true }
)

watch(
  currentIdentity,
  value => {
    const existingIdentity = props.service?.identity?.toJson() ?? null
    if (sameIdentity(existingIdentity, value)) {
      return
    }

    const nextService = props.service ?? new ServiceObject()

    if (value === null) {
      nextService.identity = null
      emit('update:service', nextService)
      return
    }

    if (nextService.identity instanceof IdentityBasic) {
      nextService.identity.identity = value.identity
      nextService.identity.secret = value.secret
    } else {
      nextService.identity = new IdentityBasic(value.identity, value.secret)
    }

    emit('update:service', nextService)
  },
  { immediate: true, deep: true }
)

function syncFromService(service?: ServiceObject) {
  const serviceIdentity = service?.identity?.toJson() ?? null

  if (serviceIdentity?.type === 'BA') {
    identity.value = serviceIdentity.identity || props.prefilledIdentity || props.emailAddress || ''
    secret.value = serviceIdentity.secret || props.prefilledSecret || ''
    return
  }

  identity.value = props.prefilledIdentity || props.emailAddress || ''
  secret.value = props.prefilledSecret || ''
}

function sameIdentity(a: ServiceIdentity | null, b: ServiceIdentity | null): boolean {
  if (a === null || b === null) {
    return a === b
  }

  return a.type === 'BA'
    && b.type === 'BA'
    && a.identity === b.identity
    && a.secret === b.secret
}
</script>

<template>
  <div class="imap-auth-panel">
    <h3 class="text-h6 mb-4">Authentication</h3>
    <p class="text-body-2 mb-6">Provide the username and password your IMAP server expects.</p>

    <v-alert type="info" variant="tonal">
      Most IMAP servers use your full email address as the username. Use an app password if your mail host requires one.
    </v-alert>

    <v-text-field
      v-model="identity"
      label="Username / Email"
      hint="Account login used by the IMAP server"
      persistent-hint
      variant="outlined"
      prepend-inner-icon="mdi-account"
      class="mb-4"
      autocomplete="username"
      autocorrect="off"
      autocapitalize="none"
      :rules="[rules.required]"
    />

    <v-text-field
      v-model="secret"
      type="password"
      label="Password"
      hint="Password or app-specific password"
      persistent-hint
      variant="outlined"
      prepend-inner-icon="mdi-lock"
      class="mb-4"
      autocomplete="current-password"
      :rules="[rules.required]"
    />
  </div>
</template>

<style scoped>
.imap-auth-panel {
  max-width: 800px;
}

.text-h6 {
  font-size: 1.25rem;
  font-weight: 500;
  line-height: 2rem;
  letter-spacing: 0.0125em;
}

.text-body-2 {
  font-size: 0.875rem;
  font-weight: 400;
  line-height: 1.25rem;
  letter-spacing: 0.0178571429em;
  color: rgba(var(--v-theme-on-surface), 0.7);
}
</style>