import { Request, Response } from 'express'
import { IUser } from '../users/models'
import { Notification } from './models'
import { IReel } from '../reels/models'
import services from '../../utils/services'
import { IChat } from '../chats/models'

async function getNotifications(req: Request, res: Response) {
  interface Payload {
    limit?: string | number
    page?: string | number
    unread?: 'true' | 'false'
  }

  try {
    let { limit = '10', page = '1', unread } = req.query as unknown as Payload
    const user = res.locals.user as IUser
    limit = +limit
    page = +page

    const match: any = {
      user: user._id,
    }
    if(unread === 'true') {
      match.$or = [
        {read: false},
        {read: {$exists: false}}
      ]
    }

    const _notifications = await Notification.find(match)
      .sort({at: -1})
      .skip((page - 1) * limit)
      .limit(limit)
      .populate({path: 'from', select: {name: 1, username: 1, photo: 1}})
      .populate({
        path: 'reel',
        select: {vectorIndex: 0}
      })
      .populate({
        path: 'comment',
        populate: [
          {
            path: 'user',
            select: { name: 1, username: 1, photo: 1 },
          },
          {
            path: 'data.user',
            select: { name: 1, username: 1, photo: 1 },
          }
        ]
      })
      .populate({
        path: 'request',
        populate: [
          {
            path: 'user',
            select: { name: 1, username: 1, photo: 1 },
          }
        ]
      })
      .populate({
        path: 'chat',
        populate: [
          {
            path: 'creator',
            select: { name: 1, username: 1, photo: 1 },
          },
          {
            path: 'user',
            select: { name: 1, username: 1, photo: 1 },
          },
          {
            path: 'participants.user',
            select: { name: 1, username: 1, photo: 1 },
          },
          {
            path: 'lastMessage',
          },
        ]
      })
      .populate({
        path: 'rewardHash',
        select: {hash: 0},
        populate: [{ path: 'reward' }]
      })
      .populate('connection follower like superLike status')
    const count = await Notification.countDocuments(match)

    const notifications = _notifications.map(e => e.toObject())
    for(const notification of notifications) {
      if(notification.reel && (notification.reel as IReel).dynamic) {
        // @ts-ignore
        notification.reel.dynamic = services.flatDynamicToNested(notification.reel.dynamic)
      }
      const chat = notification.chat as IChat | undefined
      if(chat) {
        const p = chat.participants.find((e: any) => `${e.user._id}` === `${user._id}`)
        // @ts-ignore
        chat.areYouAdmin = !!p?.isAdmin
      }
    }

    return res.json({ notifications, count })
  } catch (error) {
    console.error(error)
    return res.status(500).json({ message: 'server error' })
  }
}

async function postNotificationRead(req: Request, res: Response) {
  try {
    const user = res.locals.user as IUser
    const id = req.params.id

    const notification = await Notification.findOne({ user: user._id, _id: id })
    if (!notification) {
      return res.status(404).json({ message: 'notification not found' })
    }

    if(notification.read) {
      return res.json({ message: 'notification already marked as read' })
    }

    notification.read = true
    await notification.save()

    return res.json({ message: 'notification successfully marked as read' })
  } catch (error) {
    console.log(error)
    return res.status(500).json({ message: 'server error' })
  }
}

async function postAllNotificationsRead(req: Request, res: Response) {
  try {
    const user = res.locals.user as IUser

    await Notification.updateMany({user: user._id}, {$set: {read: true}})

    return res.json({ message: 'All unread notifications now marked as read' })
  } catch (error) {
    console.log(error)
    return res.status(500).json({ message: 'server error' })
  }
}

const controllers = {
  getNotifications,
  postNotificationRead,
  postAllNotificationsRead
}

export default controllers
