import { Request, Response } from 'express';
import { Notification } from '@models/Notification';
import { Op } from 'sequelize';
import logger from '@utils/logger';
import { notificationService } from '@services/notification.service';

export class NotificationController {
  /**
   * Get user's notifications with pagination
   */
  async getUserNotifications(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.userId;
      const { page = 1, limit = 20, unreadOnly = false } = req.query;

      if (!userId) {
        res.status(401).json({ success: false, message: 'Unauthorized' });
        return;
      }

      const where: any = { userId };
      if (unreadOnly === 'true') {
        where.isRead = false;
      }

      const offset = (Number(page) - 1) * Number(limit);

      const { rows, count } = await Notification.findAndCountAll({
        where,
        order: [['createdAt', 'DESC']],
        limit: Number(limit),
        offset
      });

      res.json({
        success: true,
        data: {
          notifications: rows,
          pagination: {
            page: Number(page),
            limit: Number(limit),
            total: count,
            totalPages: Math.ceil(count / Number(limit))
          },
          unreadCount: unreadOnly === 'true' ? count : await Notification.count({ where: { userId, isRead: false } })
        }
      });
    } catch (error: any) {
      logger.error('[Notification Controller] Error fetching notifications:', error);
      res.status(500).json({ success: false, message: error.message });
    }
  }

  /**
   * Get unread notification count
   */
  async getUnreadCount(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.userId;

      if (!userId) {
        res.status(401).json({ success: false, message: 'Unauthorized' });
        return;
      }

      const count = await Notification.count({
        where: { userId, isRead: false }
      });

      res.json({
        success: true,
        data: { unreadCount: count }
      });
    } catch (error: any) {
      logger.error('[Notification Controller] Error fetching unread count:', error);
      res.status(500).json({ success: false, message: error.message });
    }
  }

  /**
   * Mark notification as read
   */
  async markAsRead(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.userId;
      const { notificationId } = req.params;

      if (!userId) {
        res.status(401).json({ success: false, message: 'Unauthorized' });
        return;
      }

      const notification = await Notification.findOne({
        where: { notificationId, userId }
      });

      if (!notification) {
        res.status(404).json({ success: false, message: 'Notification not found' });
        return;
      }

      await notification.update({
        isRead: true,
        readAt: new Date()
      });

      res.json({
        success: true,
        message: 'Notification marked as read',
        data: { notification }
      });
    } catch (error: any) {
      logger.error('[Notification Controller] Error marking notification as read:', error);
      res.status(500).json({ success: false, message: error.message });
    }
  }

  /**
   * Mark all notifications as read
   */
  async markAllAsRead(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.userId;

      if (!userId) {
        res.status(401).json({ success: false, message: 'Unauthorized' });
        return;
      }

      await Notification.update(
        { isRead: true, readAt: new Date() },
        { where: { userId, isRead: false } }
      );

      res.json({
        success: true,
        message: 'All notifications marked as read'
      });
    } catch (error: any) {
      logger.error('[Notification Controller] Error marking all as read:', error);
      res.status(500).json({ success: false, message: error.message });
    }
  }

  /**
   * Delete notification
   */
  async deleteNotification(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.userId;
      const { notificationId } = req.params;

      if (!userId) {
        res.status(401).json({ success: false, message: 'Unauthorized' });
        return;
      }

      const deleted = await Notification.destroy({
        where: { notificationId, userId }
      });

      if (deleted === 0) {
        res.status(404).json({ success: false, message: 'Notification not found' });
        return;
      }

      res.json({
        success: true,
        message: 'Notification deleted'
      });
    } catch (error: any) {
      logger.error('[Notification Controller] Error deleting notification:', error);
      res.status(500).json({ success: false, message: error.message });
    }
  }

  /**
   * Get user's push notification subscriptions
   */
  async getUserSubscriptions(req: Request, res: Response): Promise<void> {
    try {
      const userId = (req as any).user?.userId;

      if (!userId) {
        res.status(401).json({ success: false, message: 'Unauthorized' });
        return;
      }

      const subscriptions = await notificationService.getUserSubscriptions(userId);

      res.json({
        success: true,
        data: {
          subscriptions,
          count: subscriptions.length
        }
      });
    } catch (error: any) {
      logger.error('[Notification Controller] Error fetching subscriptions:', error);
      res.status(500).json({ success: false, message: error.message });
    }
  }
}

