const Feedback = require('../models/Feedback');
const Ride = require('../models/Ride');
const RideRequest = require('../models/RideRequest');
const { User } = require('../models/user');

/**
 * @desc    Crea un feedback per un viaggio
 * @route   POST /api/trasporti/feedback
 * @access  Private
 */
const createFeedback = async (req, res) => {
  try {
    const {
      idapp,
      rideId,
      rideRequestId,
      toUserId,
      role,
      rating,
      categories,
      comment,
      pros,
      cons,
      tags,
      isPublic
    } = req.body;

    const fromUserId = req.user._id;

    // Validazione base
    if (!idapp || !rideId || !toUserId || !role || !rating) {
      return res.status(400).json({
        success: false,
        message: 'Campi obbligatori: idapp, rideId, toUserId, role, rating'
      });
    }

    // Verifica rating valido
    if (rating < 1 || rating > 5) {
      return res.status(400).json({
        success: false,
        message: 'Il rating deve essere tra 1 e 5'
      });
    }

    // Verifica che il ride esista e sia completato
    const ride = await Ride.findById(rideId);
    if (!ride) {
      return res.status(404).json({
        success: false,
        message: 'Viaggio non trovato'
      });
    }

    // Verifica che l'utente abbia partecipato al viaggio
    const wasDriver = ride.userId.toString() === fromUserId.toString();
    const wasPassenger = ride.confirmedPassengers.some(
      p => p.userId.toString() === fromUserId.toString()
    );

    if (!wasDriver && !wasPassenger) {
      return res.status(403).json({
        success: false,
        message: 'Non hai partecipato a questo viaggio'
      });
    }

    // Verifica che non stia valutando se stesso
    if (fromUserId.toString() === toUserId.toString()) {
      return res.status(400).json({
        success: false,
        message: 'Non puoi valutare te stesso'
      });
    }

    // Verifica che non esista già un feedback
    const existingFeedback = await Feedback.findOne({
      rideId,
      fromUserId,
      toUserId
    });

    if (existingFeedback) {
      return res.status(400).json({
        success: false,
        message: 'Hai già lasciato un feedback per questo utente in questo viaggio'
      });
    }

    // Crea il feedback
    const feedbackData = {
      idapp,
      rideId,
      fromUserId,
      toUserId,
      role,
      rating
    };

    if (rideRequestId) feedbackData.rideRequestId = rideRequestId;
    if (categories) feedbackData.categories = categories;
    if (comment) feedbackData.comment = comment;
    if (pros) feedbackData.pros = pros;
    if (cons) feedbackData.cons = cons;
    if (tags) feedbackData.tags = tags;
    if (isPublic !== undefined) feedbackData.isPublic = isPublic;

    // Verifica automatica se il viaggio è completato
    if (ride.status === 'completed') {
      feedbackData.isVerified = true;
    }

    const feedback = new Feedback(feedbackData);
    await feedback.save();

    // Aggiorna la media rating dell'utente destinatario
    await updateUserRating(idapp, toUserId);

    // Aggiorna flag nella richiesta se presente
    if (rideRequestId) {
      await RideRequest.findByIdAndUpdate(rideRequestId, {
        feedbackGiven: true
      });
    }

    await feedback.populate('fromUserId', 'username name surname profile.img');
    await feedback.populate('toUserId', 'username name surname');

    res.status(201).json({
      success: true,
      message: 'Feedback inviato con successo!',
      data: feedback
    });

  } catch (error) {
    console.error('Errore creazione feedback:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nella creazione del feedback',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni i feedback ricevuti da un utente
 * @route   GET /api/trasporti/feedback/user/:userId
 * @access  Public
 */
const getUserFeedback = async (req, res) => {
  try {
    const { userId } = req.params;
    const { idapp, role, page = 1, limit = 10 } = req.query;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    const query = {
      idapp,
      toUserId: userId,
      isPublic: true
    };

    if (role) {
      query.role = role;
    }

    const skip = (parseInt(page) - 1) * parseInt(limit);

    const [feedbacks, total, stats] = await Promise.all([
      Feedback.find(query)
        .populate('fromUserId', 'username name surname profile.img')
        .populate('rideId', 'departure destination dateTime')
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(parseInt(limit)),
      Feedback.countDocuments(query),
      getStatsForUser(idapp, userId)
    ]);

    res.json({
      success: true,
      data: feedbacks,
      stats,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / parseInt(limit))
      }
    });

  } catch (error) {
    console.error('Errore recupero feedbacks:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero dei feedback',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni statistiche feedback per un utente
 * @route   GET /api/trasporti/feedback/user/:userId/stats
 * @access  Public
 */
const getUserFeedbackStats = async (req, res) => {
  try {
    const { userId } = req.params;
    const { idapp } = req.query;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    const [stats, distribution] = await Promise.all([
      getStatsForUser(idapp, userId),
      getRatingDistribution(idapp, userId)
    ]);

    res.json({
      success: true,
      data: {
        ...stats,
        distribution
      }
    });

  } catch (error) {
    console.error('Errore recupero stats:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero delle statistiche',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni i feedback per un viaggio
 * @route   GET /api/trasporti/feedback/ride/:rideId
 * @access  Public (con info limitate) / Private (info complete)
 */
const getRideFeedback = async (req, res) => {
  try {
    const { rideId } = req.params;
    const { idapp } = req.query;
    const userId = req.user?._id;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    // Verifica che il ride esista
    const ride = await Ride.findById(rideId);
    if (!ride) {
      return res.status(404).json({
        success: false,
        message: 'Viaggio non trovato'
      });
    }

    // Query base per feedback pubblici
    const query = { 
      idapp, 
      rideId,
      isPublic: true
    };

    const feedbacks = await Feedback.find(query)
      .populate('fromUserId', 'username name surname profile.img')
      .populate('toUserId', 'username name surname profile.img')
      .sort({ createdAt: -1 });

    // Se l'utente è autenticato e ha partecipato, mostra info aggiuntive
    let pendingFeedbacks = [];
    let myFeedbacks = [];

    if (userId) {
      const wasDriver = ride.userId.toString() === userId.toString();
      const wasPassenger = ride.confirmedPassengers.some(
        p => p.userId.toString() === userId.toString()
      );

      if (wasDriver || wasPassenger) {
        myFeedbacks = feedbacks.filter(
          f => f.fromUserId._id.toString() === userId.toString()
        );

        if (wasDriver) {
          // Il conducente deve dare feedback ai passeggeri
          const feedbackGivenTo = myFeedbacks.map(f => f.toUserId._id.toString());
          pendingFeedbacks = ride.confirmedPassengers
            .filter(p => !feedbackGivenTo.includes(p.userId.toString()))
            .map(p => ({ userId: p.userId, role: 'passenger' }));
        } else {
          // Il passeggero deve dare feedback al conducente
          const hasGivenToDriver = myFeedbacks.some(
            f => f.toUserId._id.toString() === ride.userId.toString()
          );
          if (!hasGivenToDriver) {
            pendingFeedbacks.push({ userId: ride.userId, role: 'driver' });
          }
        }
      }
    }

    res.json({
      success: true,
      data: {
        feedbacks,
        pendingFeedbacks,
        myFeedbacks
      }
    });

  } catch (error) {
    console.error('Errore recupero feedbacks viaggio:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Verifica se l'utente può lasciare un feedback
 * @route   GET /api/trasporti/feedback/can-leave/:rideId/:toUserId
 * @access  Private
 * @note    NUOVA FUNZIONE - Era mancante!
 */
const canLeaveFeedback = async (req, res) => {
  try {
    const { rideId, toUserId } = req.params;
    const { idapp } = req.query;
    const fromUserId = req.user._id;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    // Verifica che il ride esista
    const ride = await Ride.findById(rideId);
    if (!ride) {
      return res.status(404).json({
        success: false,
        message: 'Viaggio non trovato'
      });
    }

    // Verifica che l'utente abbia partecipato al viaggio
    const wasDriver = ride.userId.toString() === fromUserId.toString();
    const wasPassenger = ride.confirmedPassengers.some(
      p => p.userId.toString() === fromUserId.toString()
    );

    if (!wasDriver && !wasPassenger) {
      return res.json({
        success: true,
        data: {
          canLeave: false,
          reason: 'Non hai partecipato a questo viaggio'
        }
      });
    }

    // Verifica che non stia valutando se stesso
    if (fromUserId.toString() === toUserId.toString()) {
      return res.json({
        success: true,
        data: {
          canLeave: false,
          reason: 'Non puoi valutare te stesso'
        }
      });
    }

    // Verifica che toUserId abbia partecipato al viaggio
    const toUserWasDriver = ride.userId.toString() === toUserId.toString();
    const toUserWasPassenger = ride.confirmedPassengers.some(
      p => p.userId.toString() === toUserId.toString()
    );

    if (!toUserWasDriver && !toUserWasPassenger) {
      return res.json({
        success: true,
        data: {
          canLeave: false,
          reason: 'L\'utente destinatario non ha partecipato a questo viaggio'
        }
      });
    }

    // Verifica che il viaggio sia completato
    if (ride.status !== 'completed') {
      return res.json({
        success: true,
        data: {
          canLeave: false,
          reason: 'Il viaggio non è ancora stato completato',
          rideStatus: ride.status
        }
      });
    }

    // Verifica che non esista già un feedback
    const existingFeedback = await Feedback.findOne({
      rideId,
      fromUserId,
      toUserId
    });

    if (existingFeedback) {
      return res.json({
        success: true,
        data: {
          canLeave: false,
          reason: 'Hai già lasciato un feedback per questo utente in questo viaggio',
          existingFeedbackId: existingFeedback._id
        }
      });
    }

    // Determina il ruolo del destinatario
    const toUserRole = toUserWasDriver ? 'driver' : 'passenger';

    // Recupera info utente destinatario
    const toUser = await User.findById(toUserId)
      .select('username name surname profile.img');

    res.json({
      success: true,
      data: {
        canLeave: true,
        toUser: {
          _id: toUser._id,
          username: toUser.username,
          name: toUser.name,
          surname: toUser.surname,
          img: toUser.profile?.img
        },
        toUserRole,
        ride: {
          _id: ride._id,
          departure: ride.departure,
          destination: ride.destination,
          dateTime: ride.dateTime
        }
      }
    });

  } catch (error) {
    console.error('Errore verifica canLeaveFeedback:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nella verifica',
      error: error.message
    });
  }
};

/**
 * @desc    Rispondi a un feedback ricevuto
 * @route   POST /api/trasporti/feedback/:id/response
 * @access  Private
 */
const respondToFeedback = async (req, res) => {
  try {
    const { id } = req.params;
    const { text } = req.body;
    const userId = req.user._id;

    if (!text) {
      return res.status(400).json({
        success: false,
        message: 'Il testo della risposta è obbligatorio'
      });
    }

    const feedback = await Feedback.findById(id);

    if (!feedback) {
      return res.status(404).json({
        success: false,
        message: 'Feedback non trovato'
      });
    }

    // Solo chi ha ricevuto il feedback può rispondere
    if (feedback.toUserId.toString() !== userId.toString()) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato a rispondere a questo feedback'
      });
    }

    // Verifica che non abbia già risposto
    if (feedback.response && feedback.response.text) {
      return res.status(400).json({
        success: false,
        message: 'Hai già risposto a questo feedback'
      });
    }

    // Aggiungi la risposta
    feedback.response = {
      text,
      createdAt: new Date()
    };
    await feedback.save();

    res.json({
      success: true,
      message: 'Risposta aggiunta',
      data: feedback
    });

  } catch (error) {
    console.error('Errore risposta feedback:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Segna un feedback come utile
 * @route   POST /api/trasporti/feedback/:id/helpful
 * @access  Private
 */
const markAsHelpful = async (req, res) => {
  try {
    const { id } = req.params;
    const userId = req.user._id;

    const feedback = await Feedback.findById(id);

    if (!feedback) {
      return res.status(404).json({
        success: false,
        message: 'Feedback non trovato'
      });
    }

    // Inizializza helpful se non esiste
    if (!feedback.helpful) {
      feedback.helpful = { count: 0, users: [] };
    }

    // Verifica se l'utente ha già segnato come utile
    const userIdStr = userId.toString();
    const alreadyMarked = feedback.helpful.users.some(
      u => u.toString() === userIdStr
    );

    if (alreadyMarked) {
      // Rimuovi il voto
      feedback.helpful.users = feedback.helpful.users.filter(
        u => u.toString() !== userIdStr
      );
      feedback.helpful.count = Math.max(0, feedback.helpful.count - 1);
    } else {
      // Aggiungi il voto
      feedback.helpful.users.push(userId);
      feedback.helpful.count += 1;
    }

    await feedback.save();

    res.json({
      success: true,
      message: alreadyMarked ? 'Voto rimosso' : 'Feedback segnato come utile',
      data: { 
        helpfulCount: feedback.helpful.count,
        isHelpful: !alreadyMarked
      }
    });

  } catch (error) {
    console.error('Errore mark helpful:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Segnala un feedback inappropriato
 * @route   POST /api/trasporti/feedback/:id/report
 * @access  Private
 */
const reportFeedback = async (req, res) => {
  try {
    const { id } = req.params;
    const { reason } = req.body;
    const userId = req.user._id;

    if (!reason) {
      return res.status(400).json({
        success: false,
        message: 'La motivazione è obbligatoria'
      });
    }

    const feedback = await Feedback.findById(id);

    if (!feedback) {
      return res.status(404).json({
        success: false,
        message: 'Feedback non trovato'
      });
    }

    // Inizializza reports se non esiste
    if (!feedback.reports) {
      feedback.reports = [];
    }

    // Verifica se l'utente ha già segnalato
    const alreadyReported = feedback.reports.some(
      r => r.userId.toString() === userId.toString()
    );

    if (alreadyReported) {
      return res.status(400).json({
        success: false,
        message: 'Hai già segnalato questo feedback'
      });
    }

    // Aggiungi la segnalazione
    feedback.reports.push({
      userId,
      reason,
      createdAt: new Date()
    });

    // Se ci sono troppe segnalazioni, nascondi automaticamente
    if (feedback.reports.length >= 3) {
      feedback.isPublic = false;
      feedback.hiddenReason = 'Nascosto automaticamente per multiple segnalazioni';
    }

    await feedback.save();

    res.json({
      success: true,
      message: 'Feedback segnalato. Lo esamineremo al più presto.'
    });

  } catch (error) {
    console.error('Errore segnalazione:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni i miei feedback dati
 * @route   GET /api/trasporti/feedback/my/given
 * @access  Private
 */
const getMyGivenFeedback = async (req, res) => {
  try {
    const userId = req.user._id;
    const { idapp, page = 1, limit = 20 } = req.query;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    const skip = (parseInt(page) - 1) * parseInt(limit);

    const [feedbacks, total] = await Promise.all([
      Feedback.find({ idapp, fromUserId: userId })
        .populate('toUserId', 'username name surname profile.img')
        .populate('rideId', 'departure destination dateTime')
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(parseInt(limit)),
      Feedback.countDocuments({ idapp, fromUserId: userId })
    ]);

    res.json({
      success: true,
      data: feedbacks,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / parseInt(limit))
      }
    });

  } catch (error) {
    console.error('Errore recupero feedback dati:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};

/**
 * @desc    Ottieni i miei feedback ricevuti
 * @route   GET /api/trasporti/feedback/my/received
 * @access  Private
 */
const getMyReceivedFeedback = async (req, res) => {
  try {
    const userId = req.user._id;
    const { idapp, page = 1, limit = 20 } = req.query;

    if (!idapp) {
      return res.status(400).json({
        success: false,
        message: 'idapp è obbligatorio'
      });
    }

    const skip = (parseInt(page) - 1) * parseInt(limit);

    const [feedbacks, total, stats] = await Promise.all([
      Feedback.find({ idapp, toUserId: userId })
        .populate('fromUserId', 'username name surname profile.img')
        .populate('rideId', 'departure destination dateTime')
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(parseInt(limit)),
      Feedback.countDocuments({ idapp, toUserId: userId }),
      getStatsForUser(idapp, userId)
    ]);

    res.json({
      success: true,
      data: feedbacks,
      stats,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / parseInt(limit))
      }
    });

  } catch (error) {
    console.error('Errore recupero feedback ricevuti:', error);
    res.status(500).json({
      success: false,
      message: 'Errore',
      error: error.message
    });
  }
};


// ============================================================
// 🔧 HELPER FUNCTIONS
// ============================================================

/**
 * Calcola le statistiche feedback per un utente
 */
async function getStatsForUser(idapp, userId) {
  try {
    const result = await Feedback.aggregate([
      { 
        $match: { 
          idapp, 
          toUserId: typeof userId === 'string' 
            ? require('mongoose').Types.ObjectId(userId) 
            : userId
        } 
      },
      {
        $group: {
          _id: null,
          averageRating: { $avg: '$rating' },
          totalFeedback: { $sum: 1 },
          asDriver: {
            $sum: { $cond: [{ $eq: ['$role', 'driver'] }, 1, 0] }
          },
          asPassenger: {
            $sum: { $cond: [{ $eq: ['$role', 'passenger'] }, 1, 0] }
          }
        }
      }
    ]);

    if (result.length === 0) {
      return {
        averageRating: 0,
        totalFeedback: 0,
        asDriver: 0,
        asPassenger: 0
      };
    }

    return {
      averageRating: Math.round(result[0].averageRating * 10) / 10,
      totalFeedback: result[0].totalFeedback,
      asDriver: result[0].asDriver,
      asPassenger: result[0].asPassenger
    };
  } catch (error) {
    console.error('Errore calcolo stats:', error);
    return {
      averageRating: 0,
      totalFeedback: 0,
      asDriver: 0,
      asPassenger: 0
    };
  }
}

/**
 * Calcola la distribuzione dei rating per un utente
 */
async function getRatingDistribution(idapp, userId) {
  try {
    const result = await Feedback.aggregate([
      { 
        $match: { 
          idapp, 
          toUserId: typeof userId === 'string' 
            ? require('mongoose').Types.ObjectId(userId) 
            : userId
        } 
      },
      {
        $group: {
          _id: '$rating',
          count: { $sum: 1 }
        }
      },
      { $sort: { _id: -1 } }
    ]);

    // Crea distribuzione completa 1-5
    const distribution = {};
    for (let i = 1; i <= 5; i++) {
      distribution[i] = 0;
    }

    result.forEach(r => {
      distribution[r._id] = r.count;
    });

    return distribution;
  } catch (error) {
    console.error('Errore calcolo distribuzione:', error);
    return { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 };
  }
}

/**
 * Aggiorna la media rating nel profilo utente
 */
async function updateUserRating(idapp, userId) {
  try {
    const stats = await getStatsForUser(idapp, userId);
    
    await User.findByIdAndUpdate(userId, {
      'profile.driverProfile.averageRating': stats.averageRating,
      'profile.driverProfile.totalFeedback': stats.totalFeedback
    });
  } catch (error) {
    console.error('Errore aggiornamento rating utente:', error);
  }
}


// ============================================================
// 📤 EXPORTS
// ============================================================

module.exports = {
  // Funzioni principali (nomi corretti per le routes)
  createFeedback,
  getUserFeedback,           // GET /feedback/user/:userId
  getUserFeedbackStats,      // GET /feedback/user/:userId/stats
  getRideFeedback,           // GET /feedback/ride/:rideId
  canLeaveFeedback,          // GET /feedback/can-leave/:rideId/:toUserId ← NUOVA!
  respondToFeedback,         // POST /feedback/:id/response
  reportFeedback,            // POST /feedback/:id/report
  markAsHelpful,             // POST /feedback/:id/helpful
  getMyGivenFeedback,        // GET /feedback/my/given
  getMyReceivedFeedback,     // GET /feedback/my/received
  
  // Alias per compatibilità (vecchi nomi)
  getFeedbacksForUser: getUserFeedback,
  getFeedbacksForRide: getRideFeedback,
  getMyGivenFeedbacks: getMyGivenFeedback,
  getMyReceivedFeedbacks: getMyReceivedFeedback,
  
  // Helper functions (esportate per uso in altri moduli)
  getStatsForUser,
  getRatingDistribution,
  updateUserRating
};