<script lang="ts" setup>
import { ref, onMounted } from 'vue'
import axios from 'axios'

interface NotificationItem {
  id: string
  type: string
  message: string
  data: Record<string, unknown>
  read: boolean
  created_at: string
}

const props = defineProps<{ modelValue: boolean }>()
const emit = defineEmits<{ 'update:modelValue': [value: boolean] }>()

const notifications = ref<NotificationItem[]>([])
const unreadCount = ref<number>(0)
const loading = ref<boolean>(false)

function resolveIcon(type: string): string {
  const icons: Record<string, string> = {
    payment_succeeded: 'tabler-credit-card',
    payment_failed: 'tabler-credit-card-off',
    subscription_created: 'tabler-rosette-discount-check',
    subscription_cancelled: 'tabler-circle-x',
    service_provisioned: 'tabler-server',
    invoice_generated: 'tabler-file-invoice',
  }
  return icons[type] ?? 'tabler-bell'
}

function resolveColor(type: string): string {
  const colors: Record<string, string> = {
    payment_succeeded: 'success',
    payment_failed: 'error',
    subscription_created: 'primary',
    subscription_cancelled: 'warning',
    service_provisioned: 'info',
    invoice_generated: 'secondary',
  }
  return colors[type] ?? 'default'
}

async function fetchNotifications(): Promise<void> {
  loading.value = true
  try {
    const response = await axios.get('/notifications')
    notifications.value = response.data.notifications
    unreadCount.value = response.data.unread_count
  } catch {
    // Silently fail
  } finally {
    loading.value = false
  }
}

async function markAsRead(id: string): Promise<void> {
  try {
    await axios.post(`/notifications/${id}/read`)
    const notification = notifications.value.find(n => n.id === id)
    if (notification) {
      notification.read = true
      unreadCount.value = Math.max(0, unreadCount.value - 1)
    }
  } catch { /* ignore */ }
}

async function markAllAsRead(): Promise<void> {
  try {
    await axios.post('/notifications/read-all')
    notifications.value.forEach(n => { n.read = true })
    unreadCount.value = 0
  } catch { /* ignore */ }
}

onMounted(() => fetchNotifications())

defineExpose({ unreadCount, fetchNotifications })
</script>

<template>
  <VNavigationDrawer
    :model-value="modelValue"
    temporary
    location="end"
    width="380"
    @update:model-value="emit('update:modelValue', $event)"
  >
    <div class="d-flex align-center justify-space-between pa-4">
      <h3 class="text-h6">Notifications</h3>
      <div class="d-flex align-center gap-2">
        <VBtn
          v-if="unreadCount > 0"
          variant="text"
          size="small"
          color="primary"
          @click="markAllAsRead"
        >
          Mark all read
        </VBtn>
        <VBtn
          icon
          variant="text"
          size="small"
          @click="emit('update:modelValue', false)"
        >
          <VIcon icon="tabler-x" />
        </VBtn>
      </div>
    </div>

    <VDivider />

    <VList v-if="notifications.length > 0" lines="two">
      <VListItem
        v-for="notification in notifications"
        :key="notification.id"
        :class="{ 'bg-surface-variant': !notification.read }"
        @click="markAsRead(notification.id)"
      >
        <template #prepend>
          <VAvatar size="40" :color="resolveColor(notification.type)" variant="tonal">
            <VIcon :icon="resolveIcon(notification.type)" size="20" />
          </VAvatar>
        </template>
        <VListItemTitle class="text-body-2 font-weight-medium">
          {{ notification.message }}
        </VListItemTitle>
        <VListItemSubtitle class="text-caption">
          {{ notification.created_at }}
        </VListItemSubtitle>
      </VListItem>
    </VList>

    <div v-else class="d-flex flex-column align-center justify-center pa-12" style="min-height: 300px;">
      <VIcon icon="tabler-bell-off" size="48" color="disabled" class="mb-4" />
      <div class="text-body-1 text-medium-emphasis">No notifications</div>
    </div>
  </VNavigationDrawer>
</template>
