<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ServiceObject } from '@KTXM/MailManager/models/service'
import { ServiceAddressObject } from '@KTXM/MailManager/models/address'

type AuxiliaryTab = 'addresses' | 'messages' | 'sync'
type DeleteMode = 'soft' | 'hard'

const props = defineProps<{
  service?: ServiceObject
}>()

const emit = defineEmits<{
  'update:service': [value: ServiceObject]
}>()

const activeTab = ref<AuxiliaryTab>('addresses')
const deleteMode = ref<DeleteMode>('soft')
const deleteDestination = ref('Trash')
const primaryAddress = ref<ServiceAddressObject>(new ServiceAddressObject())
const secondaryAddresses = ref<ServiceAddressObject[]>([])

const settingGroups = [
  {
    title: 'Addresses',
    value: 'addresses' as const,
    icon: 'mdi-at',
    description: 'Configure the primary mailbox identity and any sender aliases exposed by this service.'
  },
  {
    title: 'Messages',
    value: 'messages' as const,
    icon: 'mdi-email-outline',
    description: 'Control how message actions should be translated to operations.'
  },
  {
    title: 'Sync',
    value: 'sync' as const,
    icon: 'mdi-sync',
    description: 'Reserved for future synchronization settings.'
  },
]

const deleteModeOptions = [
  {
    title: 'Move to another mailbox',
    value: 'soft' as const,
    subtitle: 'Marks delete as a move operation and keeps the message in a destination mailbox.'
  },
  {
    title: 'Permanently delete',
    value: 'hard' as const,
    subtitle: 'Removes the message immediately without moving it first.'
  }
]

const destinationHint = computed(() => {
  if (deleteMode.value === 'hard') {
    return 'Not used when messages are deleted permanently.'
  }

  return 'Mailbox identifier or well-known role target, for example Trash.'
})

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

watch(
  [deleteMode, deleteDestination, primaryAddress, secondaryAddresses],
  () => {
    const nextService = props.service ?? new ServiceObject()
    const nextAuxiliary = {
      ...(nextService.auxiliary ?? {}),
      deleteMode: deleteMode.value,
      deleteDestination: deleteMode.value === 'soft'
        ? normalizeDeleteDestination(deleteDestination.value)
        : undefined,
    }

    if (sameAuxiliary(nextService.auxiliary ?? {}, nextAuxiliary)) {
      if (sameAddresses(nextService)) {
        return
      }
    }

    nextService.primaryAddress = primaryAddress.value.empty ? null : primaryAddress.value
    nextService.secondaryAddresses = dedupeAddresses(secondaryAddresses.value)
    nextService.auxiliary = nextAuxiliary
    emit('update:service', nextService)
  },
  { deep: true, immediate: true }
)

function syncFromService(service?: ServiceObject) {
  const auxiliary = service?.auxiliary ?? {}
  deleteMode.value = auxiliary.deleteMode === 'hard' ? 'hard' : 'soft'
  deleteDestination.value = typeof auxiliary.deleteDestination === 'string' && auxiliary.deleteDestination.length > 0
    ? auxiliary.deleteDestination
    : 'Trash'
  primaryAddress.value = service?.primaryAddress ?? new ServiceAddressObject()
  secondaryAddresses.value = service?.secondaryAddresses ?? []
}

function normalizeDeleteDestination(value: string): string {
  const trimmedValue = value.trim()
  return trimmedValue.length > 0 ? trimmedValue : 'Trash'
}

function dedupeAddresses(entries: ServiceAddressObject[]): ServiceAddressObject[] {
  const populated = entries.filter(entry => !entry.empty)
  return populated.filter((entry, index) =>
    populated.findIndex(candidate => candidate.matches(entry.address)) === index)
}

function addSecondaryAddress() {
  secondaryAddresses.value.push(new ServiceAddressObject())
}

function removeSecondaryAddress(index: number) {
  secondaryAddresses.value.splice(index, 1)
}

function validAddress(value: string): boolean | string {
  const trimmedValue = value.trim()
  return trimmedValue.length === 0 || /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(trimmedValue) || 'Invalid email address'
}

function sameAuxiliary(current: Record<string, any>, next: Record<string, any>): boolean {
  return (current.deleteMode === 'hard' ? 'hard' : 'soft') === next.deleteMode
    && (current.deleteDestination ?? undefined) === (next.deleteDestination ?? undefined)
}

function sameAddresses(service: ServiceObject): boolean {
  const nextPrimary = primaryAddress.value.empty ? null : primaryAddress.value
  const nextSecondary = dedupeAddresses(secondaryAddresses.value)
  return sameAddress(service.primaryAddress, nextPrimary)
    && service.secondaryAddresses.length === nextSecondary.length
    && service.secondaryAddresses.every((entry, index) => sameAddress(entry, nextSecondary[index]))
}

function sameAddress(current: ServiceAddressObject | null, next: ServiceAddressObject | null): boolean {
  if (current === null || next === null) {
    return current === next
  }
  return current.equals(next)
}
</script>

<template>
  <div class="jmap-auxiliary-panel">
    <div class="jmap-auxiliary-shell">
      <v-tabs
        v-model="activeTab"
        direction="vertical"
        color="primary"
        class="jmap-auxiliary-tabs"
      >
        <v-tab
          v-for="group in settingGroups"
          :key="group.value"
          :value="group.value"
          class="justify-start"
        >
          <v-icon start>{{ group.icon }}</v-icon>
          {{ group.title }}
        </v-tab>
      </v-tabs>

      <v-window v-model="activeTab" class="flex-1-1">
        <v-window-item value="addresses">
          <div class="jmap-settings-card">
            <h3 class="text-h6 mb-2">Addresses</h3>
            <p class="text-body-2 text-medium-emphasis mb-6">
              Configure the primary mailbox identity and any additional sender aliases exposed by this service.
            </p>

            <div class="text-subtitle-2 mb-2">Primary Address</div>
            <div class="d-flex ga-2 mb-6">
              <v-text-field
                v-model="primaryAddress.label"
                label="Display Name"
                variant="outlined"
                density="compact"
                hide-details="auto"
              />
              <v-text-field
                v-model="primaryAddress.address"
                label="Email Address"
                variant="outlined"
                density="compact"
                prepend-inner-icon="mdi-email-outline"
                :rules="[validAddress]"
                hide-details="auto"
              />
            </div>

            <div class="text-subtitle-2 mb-2">Secondary Addresses</div>
            <div
              v-for="(entry, index) in secondaryAddresses"
              :key="index"
              class="d-flex ga-2 mb-2"
            >
              <v-text-field
                v-model="entry.label"
                label="Display Name"
                variant="outlined"
                density="compact"
                hide-details="auto"
              />
              <v-text-field
                v-model="entry.address"
                label="Email Address"
                variant="outlined"
                density="compact"
                prepend-inner-icon="mdi-email-multiple-outline"
                :rules="[validAddress]"
                hide-details="auto"
              />
              <v-btn
                icon
                size="small"
                variant="text"
                @click="removeSecondaryAddress(index)"
              >
                <v-icon>mdi-delete-outline</v-icon>
                <v-tooltip activator="parent" location="bottom">Remove Alias</v-tooltip>
              </v-btn>
            </div>

            <v-btn
              variant="tonal"
              prepend-icon="mdi-plus"
              @click="addSecondaryAddress"
            >
              Add Alias
            </v-btn>
          </div>
        </v-window-item>

        <v-window-item value="messages">
          <div class="jmap-settings-card">
            <h3 class="text-h6 mb-2">Message Deletion</h3>
            <p class="text-body-2 text-medium-emphasis mb-6">
              Choose how the mail system should react when a delete command is issued.
            </p>

            <v-radio-group
              v-model="deleteMode"
              color="primary"
              class="mb-4"
            >
              <v-radio
                v-for="option in deleteModeOptions"
                :key="option.value"
                :value="option.value"
              >
                <template #label>
                  <div>
                    <div class="text-body-1">{{ option.title }}</div>
                    <div class="text-caption text-medium-emphasis">{{ option.subtitle }}</div>
                  </div>
                </template>
              </v-radio>
            </v-radio-group>

            <v-text-field
              v-model="deleteDestination"
              label="Delete Destination"
              variant="outlined"
              prepend-inner-icon="mdi-folder-move-outline"
              :disabled="deleteMode === 'hard'"
              :hint="destinationHint"
              persistent-hint
            />
          </div>
        </v-window-item>

        <v-window-item value="sync">
          <div class="jmap-settings-card">
            <h3 class="text-h6 mb-2">Sync Settings</h3>
            <p class="text-body-2 text-medium-emphasis mb-0">
              Additional synchronization controls can be added here as the provider grows.
            </p>
          </div>
        </v-window-item>
      </v-window>
    </div>
  </div>
</template>

<style scoped>
.jmap-auxiliary-shell {
  display: grid;
  grid-template-columns: minmax(180px, 220px) minmax(0, 1fr);
  gap: 24px;
  align-items: start;
}

.jmap-auxiliary-tabs {
  border-right: 1px solid rgba(var(--v-theme-outline), 0.16);
  padding-right: 12px;
}

.jmap-settings-card {
  padding: 4px 4px 4px 0;
}

@media (max-width: 768px) {
  .jmap-auxiliary-shell {
    grid-template-columns: 1fr;
  }

  .jmap-auxiliary-tabs {
    border-right: 0;
    border-bottom: 1px solid rgba(var(--v-theme-outline), 0.16);
    padding-right: 0;
    padding-bottom: 12px;
  }
}
</style>