import { Controller, Delete, Get, Middleware, Post, Put } from '@overnightjs/core';
import { Request, Response } from 'express';
import { auth, AuthRequest } from '../middleware/auth';
import NotificationService from '../services/NotificationService';

@Controller('api/notifications')
export class NotificationController {
    /**
     * Get all notifications for authenticated user
     */
    @Get()
    @Middleware(auth)
    async getUserNotifications(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const page = parseInt(req.query.page as string) || 1;
            const limit = parseInt(req.query.limit as string) || 20;
            const category = req.query.category as string;
            const isRead = req.query.isRead;

            const filter: any = {};
            if (category) filter.category = category;
            if (isRead !== undefined) filter.isRead = isRead === 'true';

            const result = await NotificationService.getUserNotifications(userId, page, limit, filter);
            res.json({ success: true, data: result });
        } catch (error: any) {
            console.error('Error fetching notifications:', error);
            res.status(500).json({ success: false, error: error.message });
        }
    }

    /**
     * Get unread count
     */
    @Get('unread/count')
    @Middleware(auth)
    async getUnreadCount(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const count = await NotificationService.getUnreadCount(userId);
            res.json({ success: true, data: { unreadCount: count } });
        } catch (error: any) {
            console.error('Error getting unread count:', error);
            res.status(500).json({ success: false, error: error.message });
        }
    }

    /**
     * Get single notification
     */
    @Get(':id')
    @Middleware(auth)
    async getNotification(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const notification = await NotificationService.getNotificationById(req.params.id, userId);
            res.json({ success: true, data: notification });
        } catch (error: any) {
            const statusCode = error.message.includes('not found') ? 404 : 403;
            res.status(statusCode).json({ success: false, error: error.message });
        }
    }

    /**
     * Get recent notifications
     */
    @Get('recent')
    @Middleware(auth)
    async getRecentNotifications(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const limit = parseInt(req.query.limit as string) || 10;
            const notifications = await NotificationService.getRecentNotifications(userId, limit);
            res.json({ success: true, data: notifications });
        } catch (error: any) {
            console.error('Error fetching recent notifications:', error);
            res.status(500).json({ success: false, error: error.message });
        }
    }

    /**
     * Get notification history
     */
    @Get('history/:referenceId/:referenceType')
    @Middleware(auth)
    async getNotificationHistory(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const { referenceId, referenceType } = req.params;
            const notifications = await NotificationService.getNotificationHistory(referenceId, referenceType, userId);
            res.json({ success: true, data: notifications });
        } catch (error: any) {
            console.error('Error fetching notification history:', error);
            res.status(500).json({ success: false, error: error.message });
        }
    }

    /**
     * Mark as read
     */
    @Put(':id/read')
    @Middleware(auth)
    async markAsRead(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const updated = await NotificationService.markAsRead(req.params.id, userId);
            res.json({ success: true, data: updated });
        } catch (error: any) {
            const statusCode = error.message.includes('not found') ? 404 : 403;
            res.status(statusCode).json({ success: false, error: error.message });
        }
    }

    /**
     * Mark as unread
     */
    @Put(':id/unread')
    @Middleware(auth)
    async markAsUnread(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const updated = await NotificationService.markAsUnread(req.params.id, userId);
            res.json({ success: true, data: updated });
        } catch (error: any) {
            const statusCode = error.message.includes('not found') ? 404 : 403;
            res.status(statusCode).json({ success: false, error: error.message });
        }
    }

    /**
     * Mark all as read
     */
    @Post('mark-all/read')
    @Middleware(auth)
    async markAllAsRead(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const result = await NotificationService.markAllAsRead(userId);
            res.json({ success: true, data: result });
        } catch (error: any) {
            console.error('Error marking all as read:', error);
            res.status(500).json({ success: false, error: error.message });
        }
    }

    /**
     * Delete a notification
     */
    @Delete(':id')
    @Middleware(auth)
    async deleteNotification(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            await NotificationService.deleteNotification(req.params.id, userId);
            res.json({ success: true, message: 'Notification deleted successfully' });
        } catch (error: any) {
            const statusCode = error.message.includes('not found') ? 404 : 403;
            res.status(statusCode).json({ success: false, error: error.message });
        }
    }

    /**
     * Delete all notifications
     */
    @Delete()
    @Middleware(auth)
    async deleteAllNotifications(req: Request, res: Response): Promise<void> {
        try {
            const userId = (req as AuthRequest).user?.userId;
            if (!userId) {
                res.status(401).json({ success: false, error: 'Unauthorized' });
                return;
            }

            const result = await NotificationService.deleteAllUserNotifications(userId);
            res.json({ success: true, data: result });
        } catch (error: any) {
            console.error('Error deleting all notifications:', error);
            res.status(500).json({ success: false, error: error.message });
        }
    }
}
