<script setup lang="ts">
import { format, isToday, isYesterday } from "date-fns"
import { de as deLocale } from "date-fns/locale"

type EmailAccount = {
  id: string
  email: string
  imapHost?: string | null
  hasPassword?: boolean
}

type EmailMailbox = {
  id: string
  path: string
  name: string
  specialUse?: string | null
  unseen?: number
}

type EmailAddress = {
  name?: string | null
  address?: string | null
}

type EmailMessage = {
  id: string
  accountId: string
  mailboxPath: string
  subject?: string | null
  from?: EmailAddress[]
  to?: EmailAddress[]
  cc?: EmailAddress[]
  preview?: string | null
  seen?: boolean
  flagged?: boolean
  hasAttachments?: boolean
  receivedAt?: string | null
  sentAt?: string | null
  body?: {
    text?: string | null
    html?: string | null
  } | null
  attachments?: Array<{
    id: string
    filename?: string | null
    contentType?: string | null
    size?: number | null
  }>
}

const { $api } = useNuxtApp()
const toast = useToast()

const accounts = ref<EmailAccount[]>([])
const mailboxes = ref<EmailMailbox[]>([])
const messages = ref<EmailMessage[]>([])
const selectedAccountId = ref("")
const selectedMailboxPath = ref("INBOX")
const selectedMessage = ref<EmailMessage | null>(null)
const search = ref("")
const loadingAccounts = ref(true)
const loadingMailboxes = ref(false)
const loadingMessages = ref(false)
const loadingMessage = ref(false)
const syncing = ref(false)

const selectedAccount = computed(() =>
    accounts.value.find((account) => account.id === selectedAccountId.value) || null
)

const selectedMailbox = computed(() =>
    mailboxes.value.find((mailbox) => mailbox.path === selectedMailboxPath.value) || null
)

const sortedMailboxes = computed(() => {
  const priority = (mailbox: EmailMailbox) => {
    if (mailbox.specialUse === "\\Inbox" || mailbox.path.toUpperCase() === "INBOX") return 0
    if (mailbox.specialUse === "\\Sent") return 1
    if (mailbox.specialUse === "\\Drafts") return 2
    if (mailbox.specialUse === "\\Archive") return 3
    if (mailbox.specialUse === "\\Junk") return 4
    if (mailbox.specialUse === "\\Trash") return 5
    return 9
  }

  return [...mailboxes.value].sort((first, second) =>
      priority(first) - priority(second) || first.name.localeCompare(second.name)
  )
})

const filteredMessages = computed(() => {
  const needle = search.value.trim().toLowerCase()
  if (!needle) return messages.value

  return messages.value.filter((message) => [
    message.subject,
    message.preview,
    formatAddressList(message.from),
    formatAddressList(message.to),
  ].some((value) => String(value || "").toLowerCase().includes(needle)))
})

const mailboxIcon = (mailbox: EmailMailbox) => {
  if (mailbox.specialUse === "\\Inbox" || mailbox.path.toUpperCase() === "INBOX") return "i-heroicons-inbox"
  if (mailbox.specialUse === "\\Sent") return "i-heroicons-paper-airplane"
  if (mailbox.specialUse === "\\Drafts") return "i-heroicons-document"
  if (mailbox.specialUse === "\\Archive") return "i-heroicons-archive-box"
  if (mailbox.specialUse === "\\Junk") return "i-heroicons-no-symbol"
  if (mailbox.specialUse === "\\Trash") return "i-heroicons-trash"
  return "i-heroicons-folder"
}

const mailboxLabel = (mailbox: EmailMailbox) => {
  if (mailbox.specialUse === "\\Inbox" || mailbox.path.toUpperCase() === "INBOX") return "Posteingang"
  if (mailbox.specialUse === "\\Sent") return "Gesendet"
  if (mailbox.specialUse === "\\Drafts") return "Entwürfe"
  if (mailbox.specialUse === "\\Archive") return "Archiv"
  if (mailbox.specialUse === "\\Junk") return "Spam"
  if (mailbox.specialUse === "\\Trash") return "Papierkorb"
  return mailbox.name || mailbox.path
}

const formatAddress = (address?: EmailAddress | null) => {
  if (!address) return "Unbekannt"
  return address.name || address.address || "Unbekannt"
}

const formatAddressList = (addresses?: EmailAddress[] | null) => {
  return (addresses || []).map(formatAddress).filter(Boolean).join(", ")
}

const formatMessageDate = (value?: string | null) => {
  if (!value) return ""
  const date = new Date(value)
  if (isToday(date)) return format(date, "HH:mm")
  if (isYesterday(date)) return "Gestern"
  return format(date, "dd. MMM", { locale: deLocale })
}

const formatDetailDate = (value?: string | null) => {
  if (!value) return ""
  return format(new Date(value), "dd. MMMM yyyy, HH:mm", { locale: deLocale })
}

const formatAttachmentSize = (size?: number | null) => {
  if (!size) return ""
  if (size < 1024 * 1024) return `${Math.round(size / 1024)} KB`
  return `${(size / 1024 / 1024).toFixed(1)} MB`
}

const iframeContent = computed(() => {
  const html = selectedMessage.value?.body?.html
  if (html) {
    return `<!doctype html><html><head><base target="_blank"><style>body{font-family:Arial,sans-serif;font-size:14px;line-height:1.5;color:#111827;margin:0;padding:0}img{max-width:100%;height:auto}table{max-width:100%}</style></head><body>${html}</body></html>`
  }

  const text = selectedMessage.value?.body?.text || selectedMessage.value?.preview || ""
  return `<!doctype html><html><head><style>body{font-family:Arial,sans-serif;font-size:14px;line-height:1.5;color:#111827;margin:0;padding:0;white-space:pre-wrap}</style></head><body>${escapeHtml(text)}</body></html>`
})

function escapeHtml(value: string) {
  return value
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;")
      .replace(/'/g, "&#039;")
}

async function loadAccounts() {
  loadingAccounts.value = true
  try {
    accounts.value = await $api("/api/email/accounts")
    selectedAccountId.value = accounts.value[0]?.id || ""
    if (selectedAccountId.value) {
      await loadMailboxes()
    }
  } finally {
    loadingAccounts.value = false
  }
}

async function loadMailboxes() {
  if (!selectedAccountId.value) return

  loadingMailboxes.value = true
  selectedMessage.value = null

  try {
    mailboxes.value = await $api(`/api/email/accounts/${selectedAccountId.value}/mailboxes`)
    const inbox = mailboxes.value.find((mailbox) => mailbox.specialUse === "\\Inbox" || mailbox.path.toUpperCase() === "INBOX")
    selectedMailboxPath.value = inbox?.path || mailboxes.value[0]?.path || "INBOX"
    await loadMessages()
  } finally {
    loadingMailboxes.value = false
  }
}

async function loadMessages() {
  if (!selectedAccountId.value || !selectedMailboxPath.value) return

  loadingMessages.value = true
  selectedMessage.value = null

  try {
    messages.value = await $api(`/api/email/accounts/${selectedAccountId.value}/messages`, {
      query: {
        mailbox: selectedMailboxPath.value,
        limit: 100,
      },
    })

    if (messages.value.length) {
      await selectMessage(messages.value[0])
    }
  } finally {
    loadingMessages.value = false
  }
}

async function selectMailbox(mailbox: EmailMailbox) {
  selectedMailboxPath.value = mailbox.path
  await loadMessages()
}

async function selectMessage(message: EmailMessage) {
  loadingMessage.value = true
  try {
    selectedMessage.value = await $api(`/api/email/messages/${message.id}`)
  } finally {
    loadingMessage.value = false
  }
}

async function syncAccount() {
  if (!selectedAccountId.value) return

  syncing.value = true
  try {
    const res = await $api(`/api/email/accounts/${selectedAccountId.value}/sync`, {
      method: "POST",
      body: {
        mailbox: selectedMailboxPath.value,
        limit: 100,
      },
    })

    toast.add({
      title: "E-Mails synchronisiert",
      description: `${res.synced?.[0]?.fetched || 0} neue Nachrichten geladen`,
      color: "success",
    })

    await loadMailboxes()
  } catch (err: any) {
    toast.add({
      title: "Synchronisation fehlgeschlagen",
      description: err?.data?.error || err?.message || "Das Postfach konnte nicht synchronisiert werden.",
      color: "error",
    })
  } finally {
    syncing.value = false
  }
}

watch(selectedAccountId, async (next, previous) => {
  if (next && previous && next !== previous) {
    await loadMailboxes()
  }
})

onMounted(loadAccounts)
</script>

<template>
  <UPage>
    <UDashboardNavbar>
      <template #title>
        <div class="flex items-center gap-2">
          <UIcon name="i-heroicons-envelope" class="size-5 text-primary" />
          <span class="text-lg font-semibold">E-Mail</span>
        </div>
      </template>

      <template #right>
        <UButton
            icon="i-heroicons-pencil-square"
            size="sm"
            @click="navigateTo('/email/new')"
        >
          Neue E-Mail
        </UButton>
      </template>
    </UDashboardNavbar>

    <UDashboardToolbar>
      <template #left>
        <UInput
            v-model="search"
            icon="i-heroicons-magnifying-glass"
            size="sm"
            class="w-72"
            placeholder="E-Mails durchsuchen"
        />
      </template>

      <template #right>
        <UButton
            icon="i-heroicons-cog-6-tooth"
            color="neutral"
            variant="ghost"
            size="sm"
            @click="navigateTo('/settings/emailaccounts')"
        />
        <UButton
            icon="i-heroicons-arrow-path"
            color="neutral"
            variant="soft"
            size="sm"
            :loading="syncing"
            :disabled="!selectedAccountId"
            @click="syncAccount"
        >
          Aktualisieren
        </UButton>
      </template>
    </UDashboardToolbar>

    <div class="flex h-[calc(100vh-150px)] overflow-hidden">
      <aside class="w-72 shrink-0 border-r border-(--ui-border) bg-(--ui-bg) overflow-y-auto">
        <div class="border-b border-(--ui-border) p-3">
          <USkeleton v-if="loadingAccounts" class="h-9" />
          <USelectMenu
              v-else-if="accounts.length"
              v-model="selectedAccountId"
              :items="accounts"
              label-key="email"
              value-key="id"
              class="w-full"
          />
          <UButton
              v-else
              icon="i-heroicons-plus"
              block
              @click="navigateTo('/settings/emailaccounts/create')"
          >
            E-Mail Konto
          </UButton>
        </div>

        <div v-if="loadingMailboxes" class="space-y-2 p-3">
          <USkeleton v-for="i in 6" :key="i" class="h-9" />
        </div>

        <div v-else-if="!accounts.length" class="p-4 text-sm text-dimmed">
          Lege zuerst ein E-Mail Konto an.
        </div>

        <nav v-else class="p-2">
          <button
              v-for="mailbox in sortedMailboxes"
              :key="mailbox.id"
              class="flex w-full items-center gap-2 rounded-md px-3 py-2 text-left text-sm transition-colors"
              :class="selectedMailboxPath === mailbox.path ? 'bg-primary/10 text-primary' : 'hover:bg-(--ui-bg-muted)'"
              @click="selectMailbox(mailbox)"
          >
            <UIcon :name="mailboxIcon(mailbox)" class="size-4 shrink-0" />
            <span class="min-w-0 flex-1 truncate">{{ mailboxLabel(mailbox) }}</span>
            <UBadge
                v-if="mailbox.unseen"
                size="xs"
                color="primary"
                variant="soft"
            >
              {{ mailbox.unseen }}
            </UBadge>
          </button>
        </nav>
      </aside>

      <section class="w-[390px] shrink-0 border-r border-(--ui-border) bg-(--ui-bg) overflow-y-auto">
        <div class="flex h-12 items-center justify-between border-b border-(--ui-border) px-4">
          <div class="min-w-0">
            <p class="truncate text-sm font-medium">
              {{ selectedMailbox ? mailboxLabel(selectedMailbox) : 'Postfach' }}
            </p>
            <p class="text-xs text-dimmed">
              {{ filteredMessages.length }} Nachrichten
            </p>
          </div>
        </div>

        <div v-if="loadingMessages" class="space-y-2 p-3">
          <USkeleton v-for="i in 8" :key="i" class="h-20" />
        </div>

        <TableEmptyState
            v-else-if="!filteredMessages.length"
            label="Keine E-Mails anzuzeigen"
        />

        <div v-else class="divide-y divide-(--ui-border)">
          <button
              v-for="message in filteredMessages"
              :key="message.id"
              class="block w-full border-l-2 px-4 py-3 text-left transition-colors"
              :class="selectedMessage?.id === message.id ? 'border-primary bg-primary/10' : 'border-transparent hover:bg-(--ui-bg-muted)'"
              @click="selectMessage(message)"
          >
            <div class="flex items-start justify-between gap-3">
              <p class="min-w-0 truncate text-sm" :class="message.seen ? 'font-medium' : 'font-semibold'">
                {{ formatAddress(message.from?.[0]) }}
              </p>
              <span class="shrink-0 text-xs text-dimmed">
                {{ formatMessageDate(message.receivedAt || message.sentAt) }}
              </span>
            </div>
            <p class="mt-1 truncate text-sm" :class="message.seen ? 'text-highlighted' : 'font-semibold text-highlighted'">
              {{ message.subject || '(kein Betreff)' }}
            </p>
            <div class="mt-1 flex items-center gap-2 text-xs text-dimmed">
              <UIcon
                  v-if="message.hasAttachments"
                  name="i-heroicons-paper-clip"
                  class="size-3.5"
              />
              <p class="min-w-0 flex-1 truncate">
                {{ message.preview || 'Keine Vorschau' }}
              </p>
            </div>
          </button>
        </div>
      </section>

      <main class="min-w-0 flex-1 overflow-y-auto bg-(--ui-bg)">
        <div v-if="loadingMessage" class="space-y-4 p-6">
          <USkeleton class="h-8 w-2/3" />
          <USkeleton class="h-5 w-1/3" />
          <USkeleton class="h-80" />
        </div>

        <div v-else-if="selectedMessage" class="flex min-h-full flex-col">
          <div class="border-b border-(--ui-border) px-6 py-4">
            <div class="flex items-start justify-between gap-4">
              <div class="min-w-0">
                <h1 class="truncate text-xl font-semibold text-highlighted">
                  {{ selectedMessage.subject || '(kein Betreff)' }}
                </h1>
                <p class="mt-1 text-sm text-dimmed">
                  {{ formatDetailDate(selectedMessage.receivedAt || selectedMessage.sentAt) }}
                </p>
              </div>
              <div class="flex shrink-0 items-center gap-2">
                <UButton
                    icon="i-heroicons-arrow-uturn-left"
                    color="neutral"
                    variant="soft"
                    size="sm"
                    @click="navigateTo(`/email/new?to=${encodeURIComponent(formatAddressList(selectedMessage.from))}&subject=${encodeURIComponent(`Re: ${selectedMessage.subject || ''}`)}`)"
                >
                  Antworten
                </UButton>
                <UButton
                    icon="i-heroicons-arrow-uturn-right"
                    color="neutral"
                    variant="ghost"
                    size="sm"
                    @click="navigateTo(`/email/new?subject=${encodeURIComponent(`Fw: ${selectedMessage.subject || ''}`)}`)"
                >
                  Weiterleiten
                </UButton>
              </div>
            </div>

            <div class="mt-4 grid gap-1 text-sm">
              <p>
                <span class="text-dimmed">Von:</span>
                <span class="ml-2">{{ formatAddressList(selectedMessage.from) || 'Unbekannt' }}</span>
              </p>
              <p>
                <span class="text-dimmed">An:</span>
                <span class="ml-2">{{ formatAddressList(selectedMessage.to) || selectedAccount?.email }}</span>
              </p>
              <p v-if="selectedMessage.cc?.length">
                <span class="text-dimmed">Kopie:</span>
                <span class="ml-2">{{ formatAddressList(selectedMessage.cc) }}</span>
              </p>
            </div>

            <div v-if="selectedMessage.attachments?.length" class="mt-4 flex flex-wrap gap-2">
              <div
                  v-for="attachment in selectedMessage.attachments"
                  :key="attachment.id"
                  class="flex items-center gap-2 rounded-md border border-(--ui-border) px-3 py-2 text-sm"
              >
                <UIcon name="i-heroicons-paper-clip" class="size-4 text-dimmed" />
                <span>{{ attachment.filename || 'Anhang' }}</span>
                <span class="text-xs text-dimmed">{{ formatAttachmentSize(attachment.size) }}</span>
              </div>
            </div>
          </div>

          <div class="flex-1 p-6">
            <iframe
                title="E-Mail Inhalt"
                class="h-[calc(100vh-360px)] min-h-[420px] w-full"
                sandbox="allow-popups allow-popups-to-escape-sandbox"
                :srcdoc="iframeContent"
            />
          </div>
        </div>

        <div v-else class="flex h-full items-center justify-center p-6 text-center">
          <div>
            <UIcon name="i-heroicons-envelope-open" class="mx-auto mb-3 size-10 text-dimmed" />
            <p class="font-medium">Keine E-Mail ausgewählt</p>
            <p class="mt-1 text-sm text-dimmed">Wähle links eine Nachricht aus oder synchronisiere dein Postfach.</p>
          </div>
        </div>
      </main>
    </div>
  </UPage>
</template>
