<script setup lang="ts">
import { computed, onBeforeUnmount, ref } from 'vue'
import type { EntityIdentifier } from '@MailManager/types/common'
import type { EntityObject } from '@MailManager/models'
import type { CollectionObject } from '@MailManager/models/collection'

// Props
interface Props {
  messages: EntityObject[]
  selectedMessage?: EntityObject | null
  selectionList?: EntityIdentifier[]
  selectionMode?: boolean
  selectedCollection?: CollectionObject | null
  loading?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  loading: false,
  selectionList: () => [],
  selectionMode: false,
})

// Emits
const emit = defineEmits<{
  open: [message: EntityObject]
  selectionMode: [message: EntityObject]
  selectionToggleOne: [message: EntityObject]
  selectionToggleAll: [value: boolean]
  selectionClear: []
  selectionMove: []
  selectionDelete: []
  selectionFlag: [flag: string, value: boolean]
}>()

const longPressTimer = ref<number | null>(null)
const longPressActivated = ref(false)
const suppressNextClick = ref(false)
const LONG_PRESS_MS = 400
const selectedIdSet = computed(() => new Set(props.selectionList))
const selectionCount = computed(() => props.selectionList.length ?? 0)

// Sorted messages (newest first)
const sortedMessages = computed(() => {
  return [...props.messages].sort((a, b) => {
    const dateA = timeStamp(a) ?? 0
    const dateB = timeStamp(b) ?? 0
    return dateB - dateA
  })
})

const isOpened = (message: EntityObject): boolean => {
  if (!props.selectedMessage) return false
  return (message.identifier === props.selectedMessage.identifier)
}

const isSelected = (message: EntityObject): boolean => {
  return selectedIdSet.value.has(message.identifier)
}

const timeStamp = (message: EntityObject): number | null => {
  const timestamp = message.properties.received
    || message.properties.sent
    || message.modified
    || message.created
    || null

  if (!timestamp) {
    return null
  }

  const timeValue = new Date(timestamp).getTime()
  return Number.isNaN(timeValue) ? null : timeValue
}

// Format date for display
const formatDate = (date: Date | string | number | null | undefined): string => {
  if (!date) return ''
  
  const messageDate = new Date(date)
  if (Number.isNaN(messageDate.getTime())) return ''

  const now = new Date()
  const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())
  const yesterday = new Date(today)
  yesterday.setDate(yesterday.getDate() - 1)
  
  // Today - show time
  if (messageDate >= today) {
    return messageDate.toLocaleTimeString('en-US', { 
      hour: 'numeric', 
      minute: '2-digit',
      hour12: true 
    })
  }
  
  // Yesterday
  if (messageDate >= yesterday) {
    return 'Yesterday'
  }
  
  // This year - show month and day
  if (messageDate.getFullYear() === now.getFullYear()) {
    return messageDate.toLocaleDateString('en-US', { 
      month: 'short', 
      day: 'numeric' 
    })
  }

  
  // Other years - show full date
  return messageDate.toLocaleDateString('en-US', { 
    month: 'short', 
    day: 'numeric',
    year: 'numeric'
  })
}

const isSelectionControlClick = (event: MouseEvent | KeyboardEvent): boolean => {
  return event.target instanceof Element && event.target.closest('.message-selection-checkbox') !== null
}

const handleSelectionToggleOne = (message: EntityObject) => {
  emit('selectionToggleOne', message)
}

const handleSelectionToggleAll = (value: boolean | null) => {
  emit('selectionToggleAll', value === true)
}

const handleMouseClick = (event: MouseEvent | KeyboardEvent, message: EntityObject) => {
  if (isSelectionControlClick(event)) {
    return
  }

  if (suppressNextClick.value) {
    suppressNextClick.value = false
    return
  }

  if (event.shiftKey && !props.selectionMode) {
    event.preventDefault()
    event.stopPropagation()
    emit('selectionMode', message)
    return
  }

  if (longPressActivated.value) {
    longPressActivated.value = false
    return
  }

  if (props.selectionMode) {
    emit('selectionToggleOne', message)
    return
  }

  emit('open', message)
}

const handleMouseDown = (event: MouseEvent, message: EntityObject) => {
  if (isSelectionControlClick(event)) {
    return
  }

  if (!event.shiftKey || props.selectionMode) {
    return
  }

  event.preventDefault()
  event.stopPropagation()
  suppressNextClick.value = true
  emit('selectionMode', message)
}

const handleTouchStart = (message: EntityObject) => {
  clearLongPressTimer()
  longPressActivated.value = false

  longPressTimer.value = window.setTimeout(() => {
    if (!props.selectionMode) {
      emit('selectionMode', message)
    } else {
      emit('selectionToggleOne', message)
    }

    longPressActivated.value = true
    clearLongPressTimer()
  }, LONG_PRESS_MS)
}

const handleTouchEnd = () => {
  clearLongPressTimer()
}

const handleTouchMove = () => {
  clearLongPressTimer()
}

const clearLongPressTimer = () => {
  if (longPressTimer.value !== null) {
    window.clearTimeout(longPressTimer.value)
    longPressTimer.value = null
  }
}

const handleFlag = (flag: string, value: boolean) => {
  if (props.selectionMode && selectionCount.value > 0) {
    emit('selectionFlag', flag, value)
  }
}


onBeforeUnmount(() => {
  clearLongPressTimer()
})
</script>

<template>
  <div class="message-list">
    <!-- Header with folder name and counts -->
    <div v-if="selectedCollection" class="message-list-header">
      <div class="message-list-heading">
        <h2 class="text-h6">{{ selectedCollection?.properties.label || 'Folder' }}</h2>
        <div class="folder-counts text-caption text-medium-emphasis">
          <span v-if="selectedCollection?.properties.total != null">
            <span class="unread-count">{{ selectedCollection?.properties.unread ?? 0 }}</span>
            <span class="mx-1">/</span>
            <span>{{ selectedCollection?.properties.total ?? 0 }}</span>
          </span>
          <span v-else-if="messages.length > 0">
            {{ messages.length }} loaded
          </span>
        </div>
      </div>

      <div v-if="selectionMode && messages.length > 0" class="selection-summary">
        <div class="selection-controls">
          <v-checkbox-btn
            :model-value="selectionCount !== 0"
            :indeterminate="selectionCount > 0 && selectionCount !== messages.length"
            density="compact"
            hide-details
            @update:model-value="handleSelectionToggleAll"
          />
        </div>

        <div class="selection-actions">
          <v-btn
            size="small"
            icon="mdi-folder-move-outline"
            variant="text"
            :disabled="selectionCount === 0"
            @click="emit('selectionMove')"
          >
            <v-icon>mdi-folder-move-outline</v-icon>
            <v-tooltip activator="parent" location="bottom">Move Selected</v-tooltip>
          </v-btn>
          <v-btn
            size="small"
            icon="mdi-delete-outline"
            variant="text"
            :disabled="selectionCount === 0"
            @click="emit('selectionDelete')"
          >
            <v-icon>mdi-delete-outline</v-icon>
            <v-tooltip activator="parent" location="bottom">Delete Selected</v-tooltip>
          </v-btn>
          <v-btn
            size="small"
            icon="mdi-email-open-outline"
            variant="text"
            :disabled="selectionCount === 0"
            @click="handleFlag('read', true)"
          >
            <v-icon>mdi-email-open-outline</v-icon>
            <v-tooltip activator="parent" location="bottom">Mark as Read</v-tooltip>
          </v-btn>
          <v-btn
            size="small"
            icon="mdi-email-outline"
            variant="text"
            :disabled="selectionCount === 0"
            @click="handleFlag('read', false)"
          >
            <v-icon>mdi-email-outline</v-icon>
            <v-tooltip activator="parent" location="bottom">Mark as Unread</v-tooltip>
          </v-btn>
          <v-btn
            size="small"
            icon="mdi-close"
            variant="text"
            @click="emit('selectionClear')"
          >
            <v-icon>mdi-close</v-icon>
            <v-tooltip activator="parent" location="bottom">Clear Selected</v-tooltip>
          </v-btn>
        </div>
      </div>
    </div>

    <!-- Loading state -->
    <div v-if="loading" class="pa-4">
      <v-skeleton-loader
        v-for="i in 5"
        :key="i"
        type="list-item-three-line"
        class="mb-2"
      />
    </div>

    <!-- Empty state -->
    <div v-else-if="messages.length === 0" class="pa-8 text-center">
      <v-icon size="64" color="grey-lighten-1">mdi-email-outline</v-icon>
      <div class="text-h6 mt-4 text-medium-emphasis">No messages</div>
      <div class="text-body-2 text-medium-emphasis">
        This folder is empty
      </div>
    </div>

    <!-- Message list with virtual scroll -->
    <v-virtual-scroll
      v-else
      :items="sortedMessages"
      :item-height="80"
      class="message-virtual-scroll"
    >
      <template v-slot:default="{ item: message }">
        <v-list-item
          :key="message.identifier"
          class="message-item"
          :class="{
            'opened': isOpened(message),
            'selected': isSelected(message),
            'selection-mode': selectionMode,
            'unread': !message.properties.isRead
          }"
          @mousedown="handleMouseDown($event, message)"
          @click="handleMouseClick($event, message)"
          @touchstart.passive="handleTouchStart(message)"
          @touchend="handleTouchEnd"
          @touchcancel="handleTouchEnd"
          @touchmove="handleTouchMove"
          lines="three"
        >
          <template v-slot:prepend>
            <div class="message-item-prepend">
              <v-checkbox-btn
                v-if="selectionMode || isSelected(message)"
                :model-value="isSelected(message)"
                density="compact"
                hide-details
                @click.stop
                @update:model-value="handleSelectionToggleOne(message)"
              />

              <v-avatar size="40" color="primary">
                <span class="text-white text-body-1">
                  {{ (message.properties.from?.label || message.properties.from?.address || 'U')[0].toUpperCase() }}
                </span>
              </v-avatar>
            </div>
          </template>

          <v-list-item-title class="d-flex align-center">
            <span class="flex-grow-1 text-truncate">
              {{ message.properties.from?.label || message.properties.from?.address || 'Unknown Sender' }}
            </span>
            <span class="text-caption text-medium-emphasis ml-2">
              {{ formatDate(timeStamp(message)) }}
            </span>
          </v-list-item-title>

          <v-list-item-subtitle class="text-truncate">
            {{ message.properties.subject || '(No subject)' }}
          </v-list-item-subtitle>

          <v-list-item-subtitle class="text-caption text-truncate">
            {{ '' }}
          </v-list-item-subtitle>

          <template v-slot:append>
            <div class="d-flex flex-column align-center">
              <v-icon 
                v-if="message.properties.isFlagged"
                size="small"
                color="warning"
                class="mb-1"
              >
                mdi-star
              </v-icon>
              <v-icon 
                v-if="message.properties.hasAttachments"
                size="small"
                color="grey"
              >
                mdi-paperclip
              </v-icon>
            </div>
          </template>
        </v-list-item>
        <v-divider />
      </template>
    </v-virtual-scroll>
  </div>
</template>

<style scoped lang="scss">
.message-list {
  height: 100%;
  display: flex;
  flex-direction: column;
}

.message-list-header {
  padding: 16px;
  border-bottom: 1px solid rgb(var(--v-border-color));
  background-color: rgb(var(--v-theme-surface));
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;

  .message-list-heading {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
  }

  h2 {
    margin: 0;
  }
}

.selection-summary {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.selection-controls {
  display: flex;
  align-items: center;
  gap: 4px;
}

.selection-actions {
  display: flex;
  align-items: center;
  gap: 4px;
}

.folder-counts {
  display: flex;
  align-items: center;
  
  .unread-count {
    font-weight: 600;
    color: rgb(var(--v-theme-primary));
  }
}

.message-virtual-scroll {
  flex: 1;
  overflow-y: auto;
}

.message-item {
  cursor: pointer;
  transition: background-color 0.2s;
  border-left: 3px solid transparent;
}

.message-item.selection-mode {
  cursor: default;
}

.message-item-prepend {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 72px;
}

.message-item:hover {
  background-color: rgba(var(--v-theme-on-surface), 0.04);
}

.message-item.opened {
  background-color: rgba(var(--v-theme-primary), 0.12);
  border-left-color: rgb(var(--v-theme-primary));
}

.message-item.selected:not(.opened) {
  background-color: rgba(var(--v-theme-primary), 0.08);
}

.message-item.unread {
  :deep(.v-list-item-title),
  :deep(.v-list-item-subtitle:first-of-type) {
    font-weight: 600;
  }

  :deep(.v-list-item-title),
  :deep(.v-list-item-subtitle:first-of-type),
  :deep(.v-list-item-title .text-caption) {
    color: rgb(var(--v-theme-on-surface));
  }
}

.message-item.unread:hover {
  background-color: rgba(var(--v-theme-primary), 0.1);
}

.message-item.unread.selected:not(.opened) {
  background-color: rgba(var(--v-theme-primary), 0.14);
}

@media (max-width: 960px) {
  .selection-summary {
    flex-direction: column;
    align-items: flex-start;
  }
}
</style>
