import { useDB, eq, desc, and } from '../../utils/database'
import { notifications } from '../schema'

export interface NotificationRecord {
  id: number
  userId: string
  senderName: string
  senderEmail: string | null
  senderAvatar: string | null
  body: string
  url: string
  unread: boolean
  createdAt: Date
  updatedAt: Date
}

export interface NotificationResponse {
  id: number
  unread: boolean
  sender: {
    name: string
    email?: string
    avatar?: {
      src: string
    }
  }
  body: string
  url: string
  date: string
}

/**
 * Get all notifications for a specific user
 */
export const getNotificationsByUserId = async (userId: string): Promise<NotificationResponse[]> => {
  try {
    const db = useDB()
    const results = await db
      .select()
      .from(notifications)
      .where(eq(notifications.userId, userId))
      .orderBy(desc(notifications.createdAt))

    // Transform database records to API response format
    return results.map((record) => {
      const notification: NotificationResponse = {
        id: record.id,
        unread: record.unread,
        sender: {
          name: record.senderName
        },
        body: record.body,
        url: record.url,
        date: record.createdAt.toISOString()
      }

      if (record.senderEmail) {
        notification.sender.email = record.senderEmail
      }

      if (record.senderAvatar) {
        notification.sender.avatar = {
          src: record.senderAvatar
        }
      }

      return notification
    })
  } catch (error) {
    console.error('[getNotificationsByUserId]', userId, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to get notifications'
    })
  }
}

/**
 * Get unread notifications count for a user
 */
export const getUnreadNotificationsCount = async (userId: string): Promise<number> => {
  try {
    const db = useDB()
    const results = await db
      .select()
      .from(notifications)
      .where(and(eq(notifications.userId, userId), eq(notifications.unread, true)))

    return results.length
  } catch (error) {
    console.error('[getUnreadNotificationsCount]', userId, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to get unread notifications count'
    })
  }
}

/**
 * Mark a notification as read
 */
export const markNotificationAsRead = async (
  notificationId: number,
  userId: string
): Promise<NotificationRecord | undefined> => {
  try {
    const db = useDB()
    const [updated] = await db
      .update(notifications)
      .set({
        unread: false,
        updatedAt: new Date()
      })
      .where(and(eq(notifications.id, notificationId), eq(notifications.userId, userId)))
      .returning()

    return updated as NotificationRecord | undefined
  } catch (error) {
    console.error('[markNotificationAsRead]', notificationId, userId, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to mark notification as read'
    })
  }
}

/**
 * Mark all notifications as read for a user
 */
export const markAllNotificationsAsRead = async (userId: string): Promise<void> => {
  try {
    const db = useDB()
    await db
      .update(notifications)
      .set({
        unread: false,
        updatedAt: new Date()
      })
      .where(and(eq(notifications.userId, userId), eq(notifications.unread, true)))
  } catch (error) {
    console.error('[markAllNotificationsAsRead]', userId, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to mark all notifications as read'
    })
  }
}

/**
 * Create a new notification
 */
export interface CreateNotificationPayload {
  userId: string
  senderName: string
  senderEmail?: string
  senderAvatar?: string
  body: string
  url: string
}

export const createNotification = async (
  payload: CreateNotificationPayload
): Promise<NotificationRecord> => {
  try {
    const db = useDB()
    const [result] = await db
      .insert(notifications)
      .values({
        userId: payload.userId,
        senderName: payload.senderName,
        senderEmail: payload.senderEmail ?? null,
        senderAvatar: payload.senderAvatar ?? null,
        body: payload.body,
        url: payload.url
      })
      .returning()

    return result as NotificationRecord
  } catch (error) {
    console.error('[createNotification]', payload, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to create notification'
    })
  }
}

/**
 * Delete a notification
 */
export const deleteNotification = async (
  notificationId: number,
  userId: string
): Promise<void> => {
  try {
    const db = useDB()
    await db
      .delete(notifications)
      .where(and(eq(notifications.id, notificationId), eq(notifications.userId, userId)))
  } catch (error) {
    console.error('[deleteNotification]', notificationId, userId, error)
    throw createError({
      statusCode: 500,
      statusMessage: 'Failed to delete notification'
    })
  }
}
