const express = require('express');
const router = express.Router();
const { photoAuth } = require('../middleware/photoAuth');
const { verifyGalleryAccess } = require('../middleware/gallery');
const { feedbackRateLimit, generateGuestIdentifier } = require('../middleware/feedbackRateLimit');
const feedbackService = require('../services/feedbackService');
const feedbackModeration = require('../services/feedbackModeration');
const { db, logActivity } = require('../database/db');
const logger = require('../utils/logger');
const {
  validatePhotoId,
  validateFeedbackSubmission,
  checkValidation,
  validateGuestRequirements
} = require('../utils/feedbackValidation');
const { escapeLikePattern } = require('../utils/sqlSecurity');

// Get feedback settings for a gallery
router.get('/:slug/feedback-settings',
  verifyGalleryAccess,
  async (req, res) => {
    try {
      const event = req.event;
      const settings = await feedbackService.getEventFeedbackSettings(event.id);
      
      // Only send relevant settings to guests
      const guestSettings = {
        feedback_enabled: settings.feedback_enabled,
        allow_ratings: settings.allow_ratings,
        allow_likes: settings.allow_likes,
        allow_comments: settings.allow_comments,
        allow_favorites: settings.allow_favorites,
        require_name_email: settings.require_name_email,
        show_feedback_to_guests: settings.show_feedback_to_guests
      };
      
      res.json(guestSettings);
    } catch (error) {
      logger.error('Error getting feedback settings:', error);
      res.status(500).json({ error: 'Failed to get feedback settings' });
    }
  }
);

// Get feedback for a specific photo
router.get('/:slug/photos/:photoId/feedback',
  verifyGalleryAccess,
  validatePhotoId,
  checkValidation,
  async (req, res) => {
    try {
      const { photoId } = req.params;
      const event = req.event;
      const guestIdentifier = generateGuestIdentifier(req);
      
      // Get feedback settings
      const settings = await feedbackService.getEventFeedbackSettings(event.id);
      
      if (!settings.feedback_enabled) {
        return res.status(403).json({ error: 'Feedback is not enabled for this event' });
      }
      
      // Verify photo belongs to event
      const photo = await db('photos')
        .where({ id: photoId, event_id: event.id })
        .first();
      
      if (!photo) {
        return res.status(404).json({ error: 'Photo not found' });
      }
      
      // Get feedback based on settings
      const options = {
        approved_only: true,
        include_hidden: false
      };
      
      // Include guest's own feedback even if not approved
      const feedback = await feedbackService.getPhotoFeedback(photoId, options);
      
      // Get guest's own feedback separately
      const guestFeedback = await feedbackService.getPhotoFeedback(photoId, {
        guest_identifier: guestIdentifier
      });
      
      // Combine and deduplicate
      const allFeedback = [...feedback];
      guestFeedback.forEach(gf => {
        if (!feedback.find(f => f.id === gf.id)) {
          allFeedback.push({ ...gf, is_mine: true });
        } else {
          const index = allFeedback.findIndex(f => f.id === gf.id);
          allFeedback[index].is_mine = true;
        }
      });
      
      // Filter based on what guests should see
      const visibleFeedback = settings.show_feedback_to_guests ? allFeedback : 
        allFeedback.filter(f => f.is_mine);
      
      res.json({
        feedback: visibleFeedback,
        summary: {
          average_rating: photo.average_rating || 0,
          total_ratings: await db('photo_feedback')
            .where({ photo_id: photoId, feedback_type: 'rating', is_hidden: false })
            .count('id as count')
            .first()
            .then(r => r.count),
          like_count: photo.like_count || 0,
          favorite_count: photo.favorite_count || 0,
          comment_count: await db('photo_feedback')
            .where({ 
              photo_id: photoId, 
              feedback_type: 'comment', 
              is_approved: true,
              is_hidden: false 
            })
            .count('id as count')
            .first()
            .then(r => r.count)
        },
        my_feedback: {
          rating: guestFeedback.find(f => f.feedback_type === 'rating')?.rating,
          liked: !!guestFeedback.find(f => f.feedback_type === 'like'),
          favorited: !!guestFeedback.find(f => f.feedback_type === 'favorite')
        }
      });
    } catch (error) {
      logger.error('Error getting photo feedback:', error);
      res.status(500).json({ error: 'Failed to get feedback' });
    }
  }
);

// Submit feedback for a photo
router.post('/:slug/photos/:photoId/feedback',
  verifyGalleryAccess,
  validatePhotoId,
  validateFeedbackSubmission,
  checkValidation,
  async (req, res) => {
    try {
      const { photoId } = req.params;
      const event = req.event;
      const guestIdentifier = generateGuestIdentifier(req);
      
      // Get feedback settings
      const settings = await feedbackService.getEventFeedbackSettings(event.id);
      
      if (!settings.feedback_enabled) {
        return res.status(403).json({ error: 'Feedback is not enabled for this event' });
      }
      
      // Check if specific feedback type is allowed
      const feedbackType = req.body.feedback_type;
      const typeAllowed = {
        rating: settings.allow_ratings,
        like: settings.allow_likes,
        comment: settings.allow_comments,
        favorite: settings.allow_favorites
      };
      
      if (!typeAllowed[feedbackType]) {
        return res.status(403).json({ error: `${feedbackType} feedback is not enabled` });
      }
      
      // Verify photo belongs to event
      const photo = await db('photos')
        .where({ id: photoId, event_id: event.id })
        .first();
      
      if (!photo) {
        return res.status(404).json({ error: 'Photo not found' });
      }
      
      // Validate guest requirements
      const guestValidation = await validateGuestRequirements(settings, req.body);
      if (!guestValidation.valid) {
        return res.status(400).json({ 
          error: 'Guest information required',
          errors: guestValidation.errors 
        });
      }
      
      // Apply rate limiting based on feedback type
      const rateLimitMiddleware = feedbackRateLimit(feedbackType);
      await new Promise((resolve, reject) => {
        rateLimitMiddleware(req, res, (err) => {
          if (err) reject(err);
          else resolve();
        });
      });
      
      // If we got here and response was sent (rate limited), return
      if (res.headersSent) return;
      
      // Prepare feedback data
      const feedbackData = {
        feedback_type: feedbackType,
        rating: req.body.rating,
        comment_text: req.body.comment_text,
        guest_name: req.body.guest_name,
        guest_email: req.body.guest_email,
        ip_address: req.ip || req.connection.remoteAddress,
        user_agent: req.headers['user-agent'],
        moderate_comments: settings.moderate_comments
      };
      
      // For comments, check moderation
      if (feedbackType === 'comment') {
        // Check user reputation
        const reputation = await feedbackModeration.checkUserReputation(guestIdentifier, event.id);
        
        // Moderate the comment
        const moderationResult = await feedbackModeration.moderateText(req.body.comment_text);
        
        if (!moderationResult.approved) {
          // Still save but mark as not approved
          feedbackData.is_approved = false;
          logger.warn('Comment flagged for moderation:', {
            reason: moderationResult.reason,
            violations: moderationResult.violations
          });
        } else if (reputation.autoApprove) {
          // Trusted user, auto-approve
          feedbackData.is_approved = true;
        } else if (settings.moderate_comments) {
          // Default moderation setting
          feedbackData.is_approved = false;
        }
      }
      
      // Submit feedback
      const result = await feedbackService.submitFeedback(
        photoId,
        event.id,
        feedbackData,
        guestIdentifier
      );
      
      // Log activity
      await logActivity(`guest_feedback_${feedbackType}`, {
        photo_id: photoId,
        result
      }, event.id, {
        type: 'guest',
        id: guestIdentifier.substring(0, 16),
        name: req.body.guest_name || 'Anonymous'
      });
      
      res.json({
        success: true,
        ...result,
        message: feedbackType === 'comment' && !feedbackData.is_approved ? 
          'Your comment has been submitted for moderation' : undefined
      });
    } catch (error) {
      logger.error('Error submitting feedback:', error);
      res.status(500).json({ error: 'Failed to submit feedback' });
    }
  }
);

// Get feedback summary for entire gallery
router.get('/:slug/feedback-summary',
  verifyGalleryAccess,
  async (req, res) => {
    try {
      const event = req.event;
      
      // Get feedback settings
      const settings = await feedbackService.getEventFeedbackSettings(event.id);
      
      if (!settings.feedback_enabled || !settings.show_feedback_to_guests) {
        return res.json({
          enabled: false,
          summary: null
        });
      }
      
      const summary = await feedbackService.getEventFeedbackSummary(event.id);
      
      // Filter data based on what guests should see
      const guestSummary = {
        stats: summary.stats,
        top_rated: summary.photos
          .filter(p => p.average_rating > 0)
          .slice(0, 5)
          .map(p => ({
            id: p.id,
            filename: p.filename,
            average_rating: p.average_rating,
            like_count: p.like_count
          }))
      };
      
      res.json({
        enabled: true,
        settings: {
          allow_ratings: settings.allow_ratings,
          allow_likes: settings.allow_likes,
          allow_comments: settings.allow_comments,
          allow_favorites: settings.allow_favorites
        },
        summary: guestSummary
      });
    } catch (error) {
      logger.error('Error getting feedback summary:', error);
      res.status(500).json({ error: 'Failed to get feedback summary' });
    }
  }
);

// Get user's own feedback for all photos
router.get('/:slug/my-feedback',
  verifyGalleryAccess,
  async (req, res) => {
    try {
      const event = req.event;
      const guestIdentifier = generateGuestIdentifier(req);
      
      const myFeedback = await db('photo_feedback')
        .join('photos', 'photo_feedback.photo_id', 'photos.id')
        .where('photo_feedback.event_id', event.id)
        .where('photo_feedback.guest_identifier', guestIdentifier)
        .select(
          'photo_feedback.*',
          'photos.filename',
          'photos.path'
        )
        .orderBy('photo_feedback.created_at', 'desc');
      
      res.json(myFeedback);
    } catch (error) {
      logger.error('Error getting user feedback:', error);
      res.status(500).json({ error: 'Failed to get your feedback' });
    }
  }
);

module.exports = router;