<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { useMailStore } from '@/stores/mailStore'
import { useCollectionsStore } from '@MailManager/stores/collectionsStore'
import type { ServiceObject, CollectionObject } from '@MailManager/models'
import FolderSelectionTreeNode from './FolderSelectionTreeNode.vue'

interface Props {
  modelValue: boolean
  loading?: boolean
  title?: string
  confirmText?: string
  emptyText?: string
  service?: ServiceObject | null
  disabledFolderKeys?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  loading: false,
  title: 'Move To',
  confirmText: 'Move',
  emptyText: 'No folders are available.',
  service: null,
  disabledFolderKeys: () => [],
})

const emit = defineEmits<{
  'update:modelValue': [value: boolean]
  select: [target: CollectionObject]
  cancel: []
}>()

const mailStore = useMailStore()
const collectionsStore = useCollectionsStore()

const selectedFolderKey = ref<string | null>(null)

const dialogValue = computed({
  get: () => props.modelValue,
  set: (value: boolean) => emit('update:modelValue', value),
})

interface ServiceGroup {
  service: ServiceObject
  loading: boolean
  loaded: boolean
  error: string | null
}

const serviceGroups = computed<ServiceGroup[]>(() => {
  const service = props.service
  if (!service) {
    return []
  }

  if (service.identifier === null) {
    return []
  }

  return [{
    service,
    loading: mailStore.isServiceFolderLoading(service.provider, service.identifier),
    loaded: mailStore.hasServiceFoldersLoaded(service.provider, service.identifier),
    error: mailStore.getServiceFolderError(service.provider, service.identifier),
  }]
})

const selectedFolder = computed(() => {
  if (!selectedFolderKey.value) {
    return null
  }

  const group = serviceGroups.value[0]
  if (!group) {
    return null
  }

  return getServiceFolders(group.service).find(folder => folder.identifier === selectedFolderKey.value) ?? null
})

const canConfirm = computed(() => {
  return selectedFolder.value !== null && !props.loading
})

watch(
  () => props.modelValue,
  (isOpen) => {
    if (!isOpen) {
      return
    }

    selectedFolderKey.value = null
  },
)

const getRootFolders = (service: ServiceObject): CollectionObject[] => {
  if (service.identifier === null) {
    return []
  }

  return collectionsStore.collectionsInCollection(service.provider, service.identifier, null)
}

const getServiceFolders = (service: ServiceObject): CollectionObject[] => {
  if (service.identifier === null) {
    return []
  }

  return collectionsStore.collectionsForService(service.provider, service.identifier)
}

const handleSelect = (folder: CollectionObject) => {
  selectedFolderKey.value = folder.identifier
}

const handleCancel = () => {
  emit('cancel')
  dialogValue.value = false
}

const handleConfirm = () => {
  if (!selectedFolder.value) {
    return
  }

  emit('select', selectedFolder.value)
}
</script>

<template>
  <v-dialog
    v-model="dialogValue"
    max-width="680"
  >
    <v-card>
      <v-card-title class="text-h6">
        {{ title }}
      </v-card-title>

      <v-card-text>
        <div class="folder-tree-card">
          <v-list
            density="compact"
            nav
            class="folder-tree-list"
          >
            <template
              v-for="group in serviceGroups"
              :key="`${group.service.provider}-${group.service.identifier}`"
            >
              <v-list-item
                class="account-header-item account-header-static"
                :title="group.service.label || 'Mail Account'"
                :subtitle="group.service.primaryAddress || undefined"
              >
                <template #prepend>
                  <v-icon icon="mdi-email-outline" />
                </template>
              </v-list-item>

              <FolderSelectionTreeNode
                v-for="folder in getRootFolders(group.service)"
                :key="folder.identifier"
                :folder="folder"
                :service="group.service"
                :selected-folder-key="selectedFolderKey"
                :disabled-folder-keys="disabledFolderKeys"
                @select="handleSelect"
              />

              <v-list-item
                v-if="group.loading && getServiceFolders(group.service).length === 0"
                disabled
                class="folder-status-item"
              >
                <template #prepend>
                  <v-progress-circular indeterminate size="18" width="2" color="primary" />
                </template>
                <v-list-item-title>Loading folders</v-list-item-title>
              </v-list-item>

              <v-list-item
                v-else-if="group.error && getServiceFolders(group.service).length === 0"
                disabled
                class="folder-status-item"
              >
                <template #prepend>
                  <v-icon icon="mdi-alert-circle-outline" color="error" />
                </template>
                <v-list-item-title>Folders unavailable</v-list-item-title>
                <v-list-item-subtitle>{{ group.error }}</v-list-item-subtitle>
              </v-list-item>

              <v-list-item
                v-else-if="group.loaded && getServiceFolders(group.service).length === 0"
                :title="emptyText"
                disabled
                class="folder-status-item"
              >
                <template #prepend>
                  <v-icon icon="mdi-folder-off-outline" />
                </template>
              </v-list-item>
            </template>

            <v-list-item
              v-if="serviceGroups.length === 0"
              :title="emptyText"
              disabled
            >
              <template #prepend>
                <v-icon icon="mdi-folder-off-outline" />
              </template>
            </v-list-item>
          </v-list>
        </div>
      </v-card-text>

      <v-card-actions>
        <v-spacer />

        <v-btn
          variant="text"
          :disabled="loading"
          @click="handleCancel"
        >
          Cancel
        </v-btn>

        <v-btn
          color="primary"
          variant="elevated"
          :disabled="!canConfirm"
          :loading="loading"
          @click="handleConfirm"
        >
          {{ confirmText }}
        </v-btn>
      </v-card-actions>
    </v-card>
  </v-dialog>
</template>

<style scoped>
.folder-tree-card {
  min-height: 280px;
}

.folder-tree-list {
  max-height: 380px;
  overflow-y: auto;
}

.account-header-item {
  --v-list-item-prepend-size: 22px;
  background-color: rgba(var(--v-theme-primary), 0.1);
  border-radius: 6px;
}

.account-header-static {
  margin-bottom: 4px;
}

.account-header-item :deep(.v-list-item__prepend) {
  padding-inline-start: 4px;
  margin-inline-end: 2px;
}

.folder-status-item {
  padding-inline-start: 16px;
}
</style>
