import { Router } from 'express';
import { prisma } from '../../lib/prisma.js';
import { z } from 'zod';
import jwt from 'jsonwebtoken';
const router = Router();
// Validation schemas
const createReviewSchema = z.object({
    movieId: z.number(),
    rating: z.number().min(1).max(5),
    comment: z.string().optional()
});
// Middleware to verify JWT token
const verifyToken = (req, res, next) => {
    const token = req.headers.authorization?.replace('Bearer ', '');
    if (!token) {
        return res.status(401).json({
            success: false,
            message: 'No token provided'
        });
    }
    try {
        const decoded = jwt.verify(token, process.env.JWT_SECRET || 'fallback-secret');
        req.userId = decoded.userId;
        next();
    }
    catch (error) {
        return res.status(401).json({
            success: false,
            message: 'Invalid token'
        });
    }
};
// Create a new review
router.post('/', verifyToken, async (req, res) => {
    try {
        const { movieId, rating, comment } = createReviewSchema.parse(req.body);
        const userId = req.userId;
        // Check if movie exists
        const movie = await prisma.movie.findUnique({
            where: { id: movieId }
        });
        if (!movie) {
            return res.status(404).json({
                success: false,
                message: 'Movie not found'
            });
        }
        // Check if user has already reviewed this movie
        const existingReview = await prisma.review.findFirst({
            where: {
                movieId,
                userId
            }
        });
        if (existingReview) {
            return res.status(400).json({
                success: false,
                message: 'You have already reviewed this movie'
            });
        }
        // Create the review
        const review = await prisma.review.create({
            data: {
                movieId,
                userId,
                rating,
                comment
            },
            include: {
                user: {
                    select: {
                        id: true,
                        name: true
                    }
                }
            }
        });
        // Update movie's average rating
        const allReviews = await prisma.review.findMany({
            where: { movieId },
            select: { rating: true }
        });
        const averageRating = allReviews.reduce((sum, review) => sum + review.rating, 0) / allReviews.length;
        await prisma.movie.update({
            where: { id: movieId },
            data: { ratingAvg: averageRating }
        });
        res.status(201).json({
            success: true,
            message: 'Review created successfully',
            data: { review }
        });
    }
    catch (error) {
        console.error('Error creating review:', error);
        if (error instanceof z.ZodError) {
            return res.status(400).json({
                success: false,
                message: 'Validation error',
                errors: error.issues
            });
        }
        res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
});
// Get reviews for a movie
router.get('/movie/:movieId', async (req, res) => {
    try {
        const movieId = parseInt(req.params.movieId);
        if (isNaN(movieId)) {
            return res.status(400).json({
                success: false,
                message: 'Invalid movie ID'
            });
        }
        const reviews = await prisma.review.findMany({
            where: { movieId },
            include: {
                user: {
                    select: {
                        id: true,
                        name: true
                    }
                }
            },
            orderBy: {
                createdAt: 'desc'
            }
        });
        // Calculate average rating
        const averageRating = reviews.length > 0
            ? reviews.reduce((sum, review) => sum + review.rating, 0) / reviews.length
            : 0;
        res.json({
            success: true,
            data: {
                reviews,
                averageRating,
                totalReviews: reviews.length
            }
        });
    }
    catch (error) {
        console.error('Error fetching reviews:', error);
        res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
});
// Get user's reviews
router.get('/my-reviews', verifyToken, async (req, res) => {
    try {
        const userId = req.userId;
        const reviews = await prisma.review.findMany({
            where: { userId },
            include: {
                movie: {
                    select: {
                        id: true,
                        title: true,
                        posterUrl: true
                    }
                }
            },
            orderBy: {
                createdAt: 'desc'
            }
        });
        res.json({
            success: true,
            data: { reviews }
        });
    }
    catch (error) {
        console.error('Error fetching user reviews:', error);
        res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
});
// Update review
router.put('/:id', verifyToken, async (req, res) => {
    try {
        const reviewId = parseInt(req.params.id);
        const userId = req.userId;
        const { rating, comment } = createReviewSchema.omit({ movieId: true }).parse(req.body);
        if (isNaN(reviewId)) {
            return res.status(400).json({
                success: false,
                message: 'Invalid review ID'
            });
        }
        const review = await prisma.review.findFirst({
            where: {
                id: reviewId,
                userId
            }
        });
        if (!review) {
            return res.status(404).json({
                success: false,
                message: 'Review not found'
            });
        }
        const updatedReview = await prisma.review.update({
            where: { id: reviewId },
            data: {
                rating,
                comment
            },
            include: {
                user: {
                    select: {
                        id: true,
                        name: true
                    }
                }
            }
        });
        // Update movie's average rating
        const allReviews = await prisma.review.findMany({
            where: { movieId: review.movieId },
            select: { rating: true }
        });
        const averageRating = allReviews.reduce((sum, review) => sum + review.rating, 0) / allReviews.length;
        await prisma.movie.update({
            where: { id: review.movieId },
            data: { ratingAvg: averageRating }
        });
        res.json({
            success: true,
            message: 'Review updated successfully',
            data: { review: updatedReview }
        });
    }
    catch (error) {
        console.error('Error updating review:', error);
        if (error instanceof z.ZodError) {
            return res.status(400).json({
                success: false,
                message: 'Validation error',
                errors: error.issues
            });
        }
        res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
});
// Delete review
router.delete('/:id', verifyToken, async (req, res) => {
    try {
        const reviewId = parseInt(req.params.id);
        const userId = req.userId;
        if (isNaN(reviewId)) {
            return res.status(400).json({
                success: false,
                message: 'Invalid review ID'
            });
        }
        const review = await prisma.review.findFirst({
            where: {
                id: reviewId,
                userId
            }
        });
        if (!review) {
            return res.status(404).json({
                success: false,
                message: 'Review not found'
            });
        }
        await prisma.review.delete({
            where: { id: reviewId }
        });
        // Update movie's average rating
        const allReviews = await prisma.review.findMany({
            where: { movieId: review.movieId },
            select: { rating: true }
        });
        const averageRating = allReviews.length > 0
            ? allReviews.reduce((sum, review) => sum + review.rating, 0) / allReviews.length
            : 0;
        await prisma.movie.update({
            where: { id: review.movieId },
            data: { ratingAvg: averageRating }
        });
        res.json({
            success: true,
            message: 'Review deleted successfully'
        });
    }
    catch (error) {
        console.error('Error deleting review:', error);
        res.status(500).json({
            success: false,
            message: 'Internal server error'
        });
    }
});
export default router;
