<script setup>
const toast = useToast()
const { $api } = useNuxtApp()

const status = ref(null)
const identity = ref(null)
const generalRoom = ref(null)
const matrixMessages = ref([])
const matrixMembers = ref([])
const matrixMessageDraft = ref("")
const matrixMessagesViewport = ref(null)
const loading = ref(false)
const roomProvisioning = ref(false)
const matrixMessagesLoading = ref(false)
const matrixMembersLoading = ref(false)
const matrixMessageSending = ref(false)
const matrixAutoRefreshActive = ref(false)
const lastUpdated = ref(null)
let matrixRefreshInterval = null
let matrixMessagesRequestActive = false
let matrixMembersRequestActive = false

const canUseMatrixChat = computed(() =>
  Boolean(status.value?.reachable && status.value?.provisioningConfigured)
)

const activeRoom = computed(() => ({
  key: "general",
  name: generalRoom.value?.name || "Allgemeiner Chat",
  description: generalRoom.value?.alias || "Mandantenweiter Austausch",
  exists: Boolean(generalRoom.value?.exists),
  roomId: generalRoom.value?.roomId || "",
  unread: 0
}))

const rooms = computed(() => [
  activeRoom.value,
  {
    key: "projects",
    name: "Projekt-Chats",
    description: "Nächste Ausbaustufe",
    exists: false,
    disabled: true
  },
  {
    key: "direct",
    name: "Direktnachrichten",
    description: "Nächste Ausbaustufe",
    exists: false,
    disabled: true
  }
])

const mergeMatrixMessages = (incomingMessages) => {
  const byId = new Map()

  for (const message of matrixMessages.value) {
    byId.set(message.id, message)
  }

  for (const message of incomingMessages || []) {
    byId.set(message.id, {
      ...byId.get(message.id),
      ...message,
      pending: false,
      failed: false
    })
  }

  matrixMessages.value = Array.from(byId.values())
    .sort((a, b) => (a.timestamp || 0) - (b.timestamp || 0))
}

const scrollMessagesToBottom = async () => {
  await nextTick()
  if (!matrixMessagesViewport.value) return

  matrixMessagesViewport.value.scrollTop = matrixMessagesViewport.value.scrollHeight
}

const loadChatInfo = async () => {
  loading.value = true
  try {
    const [statusRes, identityRes, roomRes] = await Promise.all([
      $api("/api/communication/matrix/status"),
      $api("/api/communication/matrix/me"),
      $api("/api/communication/matrix/rooms/general")
    ])

    status.value = statusRes
    identity.value = identityRes
    generalRoom.value = roomRes
    lastUpdated.value = new Date()

    if (roomRes?.exists && canUseMatrixChat.value) {
      await loadGeneralChat({ silent: true, includeMembers: true })
    }
  } catch (error) {
    toast.add({
      title: "Chat konnte nicht geladen werden",
      color: "error"
    })
  } finally {
    loading.value = false
  }
}

const provisionGeneralRoom = async () => {
  roomProvisioning.value = true
  try {
    const res = await $api("/api/communication/matrix/rooms/general/provision", {
      method: "POST"
    })

    generalRoom.value = {
      tenantId: res.tenantId,
      tenantName: res.tenantName,
      key: res.key,
      name: res.name,
      alias: res.alias,
      exists: true,
      roomId: res.roomId,
      servers: res.servers || []
    }

    toast.add({
      title: res.alreadyExisted ? "Allgemeiner Chat ist bereit" : "Allgemeiner Chat erstellt",
      color: "success"
    })

    await loadGeneralChat({ includeMembers: true })
  } catch (error) {
    toast.add({
      title: "Allgemeiner Chat konnte nicht erstellt werden",
      color: "error"
    })
  } finally {
    roomProvisioning.value = false
  }
}

const loadGeneralMessages = async ({ silent = false } = {}) => {
  if (!canUseMatrixChat.value || !generalRoom.value?.exists) return
  if (matrixMessagesRequestActive) return

  matrixMessagesRequestActive = true
  if (!silent) matrixMessagesLoading.value = true

  try {
    const res = await $api("/api/communication/matrix/rooms/general/messages")
    mergeMatrixMessages(res.messages || [])
    generalRoom.value = {
      ...generalRoom.value,
      alias: res.alias || generalRoom.value?.alias,
      exists: true,
      roomId: res.roomId || generalRoom.value?.roomId
    }
    await scrollMessagesToBottom()
  } catch (error) {
    if (!silent) {
      toast.add({
        title: "Nachrichten konnten nicht geladen werden",
        color: "error"
      })
    }
  } finally {
    matrixMessagesRequestActive = false
    if (!silent) matrixMessagesLoading.value = false
  }
}

const loadGeneralMembers = async ({ silent = false } = {}) => {
  if (!canUseMatrixChat.value || !generalRoom.value?.exists) return
  if (matrixMembersRequestActive) return

  matrixMembersRequestActive = true
  if (!silent) matrixMembersLoading.value = true

  try {
    const res = await $api("/api/communication/matrix/rooms/general/members")
    matrixMembers.value = res.members || []
  } catch (error) {
    if (!silent) {
      toast.add({
        title: "Teilnehmer konnten nicht geladen werden",
        color: "error"
      })
    }
  } finally {
    matrixMembersRequestActive = false
    if (!silent) matrixMembersLoading.value = false
  }
}

const loadGeneralChat = async ({ silent = false, includeMembers = false } = {}) => {
  await loadGeneralMessages({ silent })

  if (includeMembers) {
    await loadGeneralMembers({ silent })
  }
}

const sendMatrixMessage = async () => {
  const text = matrixMessageDraft.value.trim()
  if (!text || !canUseMatrixChat.value || !generalRoom.value?.exists) return

  const optimisticId = `pending-${Date.now()}`
  const optimisticMessage = {
    id: optimisticId,
    sender: identity.value?.matrixUserId || "Du",
    senderDisplayName: identity.value?.displayName || "Du",
    body: text,
    timestamp: Date.now(),
    own: true,
    pending: true,
    failed: false
  }

  matrixMessages.value = [
    ...matrixMessages.value,
    optimisticMessage
  ]
  matrixMessageDraft.value = ""
  await scrollMessagesToBottom()

  matrixMessageSending.value = true
  try {
    const message = await $api("/api/communication/matrix/rooms/general/messages", {
      method: "POST",
      body: { text }
    })

    matrixMessages.value = matrixMessages.value.map((item) =>
      item.id === optimisticId ? message : item
    )
  } catch (error) {
    matrixMessages.value = matrixMessages.value.map((item) =>
      item.id === optimisticId ? { ...item, pending: false, failed: true } : item
    )
    toast.add({
      title: "Nachricht konnte nicht gesendet werden",
      color: "error"
    })
  } finally {
    matrixMessageSending.value = false
  }
}

const startMatrixAutoRefresh = () => {
  if (matrixRefreshInterval) return

  matrixAutoRefreshActive.value = true
  matrixRefreshInterval = window.setInterval(() => {
    if (!document.hidden && canUseMatrixChat.value && generalRoom.value?.exists) {
      loadGeneralChat({ silent: true })
    }
  }, 15000)
}

const stopMatrixAutoRefresh = () => {
  if (!matrixRefreshInterval) return

  window.clearInterval(matrixRefreshInterval)
  matrixRefreshInterval = null
  matrixAutoRefreshActive.value = false
}

const formatMessageTime = (timestamp) => {
  if (!timestamp) return ""

  return new Intl.DateTimeFormat("de-DE", {
    dateStyle: "short",
    timeStyle: "short"
  }).format(new Date(timestamp))
}

const formatLastUpdated = computed(() => {
  if (!lastUpdated.value) return "Noch nicht aktualisiert"

  return new Intl.DateTimeFormat("de-DE", {
    hour: "2-digit",
    minute: "2-digit"
  }).format(lastUpdated.value)
})

watch(
  () => matrixMessages.value.length,
  () => scrollMessagesToBottom()
)

onMounted(async () => {
  await loadChatInfo()
  startMatrixAutoRefresh()
})

onBeforeUnmount(stopMatrixAutoRefresh)
</script>

<template>
  <div class="flex min-h-0 flex-1 overflow-hidden">
    <aside class="hidden w-72 shrink-0 flex-col border-r border-default bg-default lg:flex">
      <div class="border-b border-default p-4">
        <div class="flex items-center justify-between gap-3">
          <div>
            <h1 class="text-lg font-semibold text-highlighted">
              Chat
            </h1>
            <p class="text-xs text-muted">
              {{ formatLastUpdated }}
            </p>
          </div>
          <UButton
              icon="i-heroicons-arrow-path"
              color="neutral"
              variant="ghost"
              :loading="loading || matrixMessagesLoading"
              :disabled="!canUseMatrixChat"
              @click="loadGeneralChat({ includeMembers: true })"
          />
        </div>
      </div>

      <div class="flex-1 overflow-y-auto p-3">
        <button
            v-for="room in rooms"
            :key="room.key"
            type="button"
            class="mb-1 flex w-full items-center gap-3 rounded-md px-3 py-2 text-left transition"
            :class="room.disabled ? 'cursor-not-allowed opacity-50' : 'bg-muted text-highlighted'"
            :disabled="room.disabled"
        >
          <span class="flex size-9 shrink-0 items-center justify-center rounded-md bg-primary/10 text-primary">
            <UIcon name="i-heroicons-chat-bubble-left-right" class="size-5" />
          </span>
          <span class="min-w-0 flex-1">
            <span class="block truncate text-sm font-medium">{{ room.name }}</span>
            <span class="block truncate text-xs text-muted">{{ room.description }}</span>
          </span>
          <UBadge
              v-if="room.exists"
              color="success"
              variant="soft"
              size="xs"
          >
            aktiv
          </UBadge>
        </button>
      </div>

      <div class="border-t border-default p-3">
        <UButton
            to="/communication"
            icon="i-heroicons-cog-6-tooth"
            color="neutral"
            variant="outline"
            block
        >
          Matrix-Setup
        </UButton>
      </div>
    </aside>

    <main class="flex min-w-0 flex-1 flex-col bg-muted">
      <header class="flex shrink-0 items-center justify-between gap-3 border-b border-default bg-default px-4 py-3">
        <div class="min-w-0">
          <div class="flex items-center gap-2">
            <h2 class="truncate text-base font-semibold text-highlighted">
              {{ activeRoom.name }}
            </h2>
            <UBadge
                v-if="matrixAutoRefreshActive && generalRoom?.exists"
                color="success"
                variant="soft"
                size="xs"
            >
              Live
            </UBadge>
          </div>
          <p class="truncate text-xs text-muted">
            <span v-if="matrixMembers.length">{{ matrixMembers.length }} Teilnehmer</span>
            <span v-else>{{ activeRoom.description }}</span>
          </p>
        </div>

        <div class="flex items-center gap-2">
          <UButton
              class="lg:hidden"
              to="/communication"
              icon="i-heroicons-cog-6-tooth"
              color="neutral"
              variant="outline"
          />
          <UButton
              icon="i-heroicons-arrow-path"
              color="neutral"
              variant="outline"
              :loading="matrixMessagesLoading"
              :disabled="!canUseMatrixChat || !generalRoom?.exists"
              @click="loadGeneralChat({ includeMembers: true })"
          >
            Laden
          </UButton>
        </div>
      </header>

      <div
          v-if="status && (!status.reachable || !status.provisioningConfigured)"
          class="border-b border-default bg-default px-4 py-3"
      >
        <UAlert
            icon="i-heroicons-exclamation-triangle"
            color="warning"
            variant="soft"
            title="Matrix ist noch nicht bereit"
            description="Bitte prüfe das Matrix-Setup, bevor der Chat genutzt wird."
        />
      </div>

      <div
          v-else-if="status && !generalRoom?.exists"
          class="border-b border-default bg-default px-4 py-3"
      >
        <UAlert
            icon="i-heroicons-chat-bubble-left-right"
            color="primary"
            variant="soft"
            title="Allgemeiner Chat ist noch nicht eingerichtet"
            description="Lege den mandantenweiten Startraum an, um FEDEO als Chatplattform zu nutzen."
        >
          <template #actions>
            <UButton
                icon="i-heroicons-plus"
                :loading="roomProvisioning"
                @click="provisionGeneralRoom"
            >
              Chat erstellen
            </UButton>
          </template>
        </UAlert>
      </div>

      <div
          ref="matrixMessagesViewport"
          class="min-h-0 flex-1 space-y-3 overflow-y-auto p-4 sm:p-5"
      >
        <div
            v-if="!matrixMessages.length && !matrixMessagesLoading"
            class="flex h-full min-h-64 items-center justify-center text-sm text-muted"
        >
          Noch keine Nachrichten im allgemeinen Chat.
        </div>

        <div
            v-for="message in matrixMessages"
            :key="message.id"
            class="flex"
            :class="message.own ? 'justify-end' : 'justify-start'"
        >
          <div
              class="max-w-[82%] rounded-lg px-3 py-2 shadow-sm sm:max-w-[68%]"
              :class="[
                message.own ? 'bg-primary text-inverted' : 'bg-default text-highlighted',
                message.pending ? 'opacity-70' : '',
                message.failed ? 'bg-error text-inverted' : ''
              ]"
          >
            <div class="mb-1 flex flex-wrap items-center gap-x-2 gap-y-1 text-[11px] opacity-75">
              <span class="truncate font-medium">
                {{ message.own ? "Du" : message.senderDisplayName || message.sender }}
              </span>
              <span>{{ formatMessageTime(message.timestamp) }}</span>
              <span v-if="message.pending">wird gesendet</span>
              <span v-if="message.failed">nicht gesendet</span>
            </div>
            <p class="whitespace-pre-wrap break-words text-sm">
              {{ message.body }}
            </p>
          </div>
        </div>
      </div>

      <form
          class="flex shrink-0 gap-2 border-t border-default bg-default p-3"
          @submit.prevent="sendMatrixMessage"
      >
        <UInput
            v-model="matrixMessageDraft"
            class="min-w-0 flex-1"
            placeholder="Nachricht schreiben"
            :disabled="matrixMessageSending || !canUseMatrixChat || !generalRoom?.exists"
            @keydown.enter.exact.prevent="sendMatrixMessage"
        />
        <UButton
            type="submit"
            icon="i-heroicons-paper-airplane"
            :loading="matrixMessageSending"
            :disabled="!matrixMessageDraft.trim() || !canUseMatrixChat || !generalRoom?.exists"
        >
          Senden
        </UButton>
      </form>
    </main>

    <aside class="hidden w-80 shrink-0 border-l border-default bg-default xl:block">
      <div class="border-b border-default p-4">
        <h3 class="text-sm font-semibold text-highlighted">
          Raumdetails
        </h3>
        <p class="mt-1 break-all font-mono text-xs text-muted">
          {{ generalRoom?.roomId || generalRoom?.alias || "Noch kein Matrix-Raum" }}
        </p>
      </div>

      <div class="space-y-5 p-4">
        <div>
          <div class="mb-2 flex items-center justify-between gap-2">
            <h4 class="text-xs font-medium uppercase text-muted">
              Teilnehmer
            </h4>
            <UButton
                icon="i-heroicons-arrow-path"
                color="neutral"
                variant="ghost"
                size="xs"
                :loading="matrixMembersLoading"
                :disabled="!canUseMatrixChat || !generalRoom?.exists"
                @click="loadGeneralMembers"
            />
          </div>

          <div class="space-y-2">
            <div
                v-for="member in matrixMembers"
                :key="member.userId"
                class="flex items-center gap-2"
            >
              <span class="flex size-8 shrink-0 items-center justify-center rounded-md bg-muted text-xs font-medium text-highlighted">
                {{ (member.displayName || member.userId || "?").slice(0, 1).toUpperCase() }}
              </span>
              <div class="min-w-0">
                <p class="truncate text-sm font-medium text-highlighted">
                  {{ member.displayName || member.userId }}
                </p>
                <p class="truncate text-xs text-muted">
                  {{ member.userId }}
                </p>
              </div>
            </div>

            <p
                v-if="!matrixMembers.length"
                class="text-sm text-muted"
            >
              Noch keine Teilnehmer geladen.
            </p>
          </div>
        </div>

        <div>
          <h4 class="mb-2 text-xs font-medium uppercase text-muted">
            Eigene Identität
          </h4>
          <p class="break-all font-mono text-xs text-highlighted">
            {{ identity?.matrixUserId || "-" }}
          </p>
        </div>
      </div>
    </aside>
  </div>
</template>
