import { ref, computed, watch } from 'vue'
import type { Ref } from 'vue'

export interface Notification {
  id: string
  type: 'info' | 'warning' | 'success' | 'error'
  title: string
  message: string
  timestamp: number
  read: boolean
  origin: 'toast' | 'backend' | 'manual'
  metadata?: Record<string, any>
}

const notifications: Ref<Notification[]> = ref([])
const unreadCount = computed(() => notifications.value.filter(n => !n.read).length)

// Días para retención de notificaciones
const RETENTION_DAYS = 30
const STORAGE_KEY_PREFIX = 'notifications-'

let currentUserId: string | null = null
let isInitialized = false

/**
 * Obtiene la clave de localStorage para el usuario actual
 */
function getStorageKey(userId: string): string {
  return `${STORAGE_KEY_PREFIX}${userId}`
}

/**
 * Carga las notificaciones desde localStorage
 */
function loadNotifications(userId: string): Notification[] {
  if (process.client) {
    const key = getStorageKey(userId)
    const stored = localStorage.getItem(key)

    if (stored) {
      try {
        const parsed = JSON.parse(stored) as Notification[]
        // Limpiar notificaciones antiguas (> RETENTION_DAYS días)
        const cutoffTime = Date.now() - (RETENTION_DAYS * 24 * 60 * 60 * 1000)
        return parsed.filter(n => n.timestamp > cutoffTime)
      } catch (error) {
        console.error('Error al parsear notificaciones:', error)
        return []
      }
    }
  }
  return []
}

/**
 * Guarda las notificaciones en localStorage
 */
function saveNotifications(userId: string, notifs: Notification[]): void {
  if (process.client) {
    const key = getStorageKey(userId)
    localStorage.setItem(key, JSON.stringify(notifs))
  }
}

/**
 * Limpia las notificaciones del usuario actual del localStorage
 */
function clearStorageForUser(userId: string): void {
  if (process.client) {
    const key = getStorageKey(userId)
    localStorage.removeItem(key)
  }
}

/**
 * Sincronización entre pestañas
 */
function setupStorageSync(userId: string): void {
  if (process.client) {
    const key = getStorageKey(userId)

    const handleStorageChange = (event: StorageEvent) => {
      if (event.key === key && event.newValue) {
        try {
          notifications.value = JSON.parse(event.newValue)
        } catch (error) {
          console.error('Error al sincronizar notificaciones:', error)
        }
      }
    }

    window.addEventListener('storage', handleStorageChange)

    // Cleanup
    return () => {
      window.removeEventListener('storage', handleStorageChange)
    }
  }
}

/**
 * Composable principal para gestionar notificaciones
 */
export function useNotifications() {
  const { user } = useAuthentik()

  /**
   * Inicializa el sistema de notificaciones para el usuario actual
   */
  function initialize(): void {
    if (!user.value || !user.value.uid) {
      console.warn('No se puede inicializar notificaciones sin usuario autenticado')
      notifications.value = []
      currentUserId = null
      isInitialized = false
      return
    }

    const userId = user.value.uid

    // Si cambia el usuario, limpiar y recargar
    if (currentUserId !== userId) {
      currentUserId = userId
      notifications.value = loadNotifications(userId)

      // Guardar automáticamente cuando cambien las notificaciones
      watch(notifications, (newNotifications) => {
        if (currentUserId) {
          saveNotifications(currentUserId, newNotifications)
        }
      }, { deep: true })

      // Configurar sincronización entre pestañas
      setupStorageSync(userId)

      isInitialized = true
    }
  }

  /**
   * Agrega una nueva notificación
   */
  function addNotification(
    notification: Omit<Notification, 'id' | 'timestamp' | 'read'>
  ): void {
    if (!isInitialized) {
      initialize()
    }

    const newNotification: Notification = {
      ...notification,
      id: `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
      timestamp: Date.now(),
      read: false
    }

    notifications.value.unshift(newNotification)
  }

  /**
   * Marca una notificación como leída
   */
  function markAsRead(notificationId: string): void {
    const notification = notifications.value.find(n => n.id === notificationId)
    if (notification) {
      notification.read = true
    }
  }

  /**
   * Marca todas las notificaciones como leídas
   */
  function markAllAsRead(): void {
    notifications.value.forEach(n => n.read = true)
  }

  /**
   * Elimina una notificación específica
   */
  function removeNotification(notificationId: string): void {
    const index = notifications.value.findIndex(n => n.id === notificationId)
    if (index !== -1) {
      notifications.value.splice(index, 1)
    }
  }

  /**
   * Elimina todas las notificaciones
   */
  function clearAll(): void {
    notifications.value = []
    if (currentUserId) {
      clearStorageForUser(currentUserId)
    }
  }

  /**
   * Elimina notificaciones antiguas (> RETENTION_DAYS días)
   */
  function cleanupOldNotifications(): void {
    const cutoffTime = Date.now() - (RETENTION_DAYS * 24 * 60 * 60 * 1000)
    notifications.value = notifications.value.filter(n => n.timestamp > cutoffTime)
  }

  /**
   * Obtiene notificaciones filtradas
   */
  function getFilteredNotifications(options?: {
    type?: Notification['type'][]
    read?: boolean
    search?: string
    limit?: number
  }): Notification[] {
    let filtered = [...notifications.value]

    if (options?.type && options.type.length > 0) {
      filtered = filtered.filter(n => options.type!.includes(n.type))
    }

    if (options?.read !== undefined) {
      filtered = filtered.filter(n => n.read === options.read)
    }

    if (options?.search) {
      const searchLower = options.search.toLowerCase()
      filtered = filtered.filter(n =>
        n.title.toLowerCase().includes(searchLower) ||
        n.message.toLowerCase().includes(searchLower)
      )
    }

    if (options?.limit) {
      filtered = filtered.slice(0, options.limit)
    }

    return filtered
  }

  // Auto-inicializar cuando haya usuario
  if (user.value && user.value.uid) {
    initialize()
  }

  // Re-inicializar si cambia el usuario
  watch(() => user.value?.uid, (newUid) => {
    if (newUid) {
      initialize()
    } else {
      notifications.value = []
      currentUserId = null
      isInitialized = false
    }
  })

  return {
    notifications: computed(() => notifications.value),
    unreadCount,
    addNotification,
    markAsRead,
    markAllAsRead,
    removeNotification,
    clearAll,
    cleanupOldNotifications,
    getFilteredNotifications,
    initialize
  }
}
