const RideRequest = require('../models/RideRequest');
const Ride = require('../models/Ride');
const Chat = require('../models/Chat');
const Message = require('../models/Message');

/**
 * @desc    Crea una richiesta di passaggio
 * @route   POST /api/trasporti/requests
 * @access  Private
 */
const createRequest = async (req, res) => {
  try {
    const {
      idapp,
      rideId,
      message,
      pickupPoint,
      dropoffPoint,
      useOriginalRoute,
      seatsRequested,
      hasLuggage,
      luggageSize,
      hasPackages,
      packageDescription,
      hasPets,
      petType,
      petSize,
      specialNeeds,
      contribution,
    } = req.body;

    const passengerId = req.user._id;

    // Validazione
    if (!idapp || !rideId) {
      return res.status(400).json({
        success: false,
        message: 'idapp e rideId sono obbligatori',
      });
    }

    // 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 non sia il proprio viaggio
    if (ride.userId.toString() === passengerId.toString()) {
      return res.status(400).json({
        success: false,
        message: 'Non puoi richiedere un passaggio per il tuo stesso viaggio',
      });
    }

    // Verifica che non ci sia già una richiesta pendente/accettata
    const existingRequest = await RideRequest.findOne({
      rideId,
      passengerId,
      status: { $in: ['pending', 'accepted'] },
    });

    if (existingRequest) {
      return res.status(400).json({
        success: false,
        message: 'Hai già una richiesta attiva per questo viaggio',
      });
    }

    // Verifica disponibilità posti
    const seats = seatsRequested || 1;
    if (ride.type === 'offer' && ride.passengers.available < seats) {
      return res.status(400).json({
        success: false,
        message: `Posti insufficienti. Disponibili: ${ride.passengers.available}`,
      });
    }

    // Crea la richiesta
    const requestData = {
      idapp,
      rideId,
      passengerId,
      driverId: ride.userId,
      seatsRequested: seats,
      useOriginalRoute: useOriginalRoute !== false,
    };

    if (message) requestData.message = message;
    if (pickupPoint) requestData.pickupPoint = pickupPoint;
    if (dropoffPoint) requestData.dropoffPoint = dropoffPoint;
    if (hasLuggage !== undefined) {
      requestData.hasLuggage = hasLuggage;
      requestData.luggageSize = luggageSize || 'small';
    }
    if (hasPackages !== undefined) {
      requestData.hasPackages = hasPackages;
      requestData.packageDescription = packageDescription;
    }
    if (hasPets !== undefined) {
      requestData.hasPets = hasPets;
      requestData.petType = petType;
      requestData.petSize = petSize;
    }
    if (specialNeeds) requestData.specialNeeds = specialNeeds;
    if (contribution) requestData.contribution = contribution;

    const rideRequest = new RideRequest(requestData);
    await rideRequest.save();

    // Popola i dati per la risposta
    await rideRequest.populate('passengerId', 'username name surname profile.img');
    await rideRequest.populate('rideId', 'departure destination dateTime');

    // Crea o recupera la chat tra passeggero e conducente
    const chat = await Chat.findOrCreateDirect(idapp, passengerId, ride.userId, rideId);

    // Invia messaggio automatico nella chat
    if (message) {
      const chatMessage = new Message({
        idapp,
        chatId: chat._id,
        senderId: passengerId,
        text: message,
        type: 'ride_request',
        metadata: {
          rideId,
          rideRequestId: rideRequest._id,
        },
      });
      await chatMessage.save();
    }

    // TODO: Inviare notifica push al conducente

    res.status(201).json({
      success: true,
      message: 'Richiesta di passaggio inviata!',
      data: rideRequest,
      chatId: chat._id,
    });
  } catch (error) {
    console.error('Errore creazione richiesta:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nella creazione della richiesta',
      error: error.message,
    });
  }
};

/**
 * @desc    Ottieni le richieste per un viaggio (per il conducente)
 * @route   GET /api/trasporti/requests/ride/:rideId
 * @access  Private
 */
const getRequestsForRide = async (req, res) => {
  try {
    const { rideId } = req.params;
    const { idapp, status } = req.query;
    const userId = req.user._id;

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

    if (ride.userId.toString() !== userId.toString()) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato a vedere le richieste di questo viaggio',
      });
    }

    const query = { idapp, rideId };
    if (status) {
      query.status = status;
    }

    const requests = await RideRequest.find(query)
      .populate(
        'passengerId',
        'username name surname profile.img profile.Cell profile.driverProfile.averageRating profile.driverProfile.ridesCompletedAsPassenger'
      )
      .sort({ createdAt: -1 });

    res.json({
      success: true,
      data: requests,
    });
  } catch (error) {
    console.error('Errore recupero richieste:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero delle richieste',
      error: error.message,
    });
  }
};

/**
 * @desc    Ottieni le mie richieste (come passeggero)
 * @route   GET /api/trasporti/requests/my
 * @access  Private
 */
const getMyRequests = async (req, res) => {
  try {
    const userId = req.user._id;
    const { idapp, status, page = 1, limit = 20 } = req.query;

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

    const query = { idapp, passengerId: userId };
    if (status) {
      query.status = status;
    }

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

    const [requests, total] = await Promise.all([
      RideRequest.find(query)
        .populate({
          path: 'rideId',
          populate: {
            path: 'userId',
            select: 'username name surname profile.img profile.Cell profile.driverProfile.averageRating',
          },
        })
        .sort({ createdAt: -1 })
        .skip(skip)
        .limit(parseInt(limit)),
      RideRequest.countDocuments(query),
    ]);

    res.json({
      success: true,
      data: requests,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total,
        pages: Math.ceil(total / parseInt(limit)),
      },
    });
  } catch (error) {
    console.error('Errore recupero mie richieste:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero delle tue richieste',
      error: error.message,
    });
  }
};

/**
 * @desc    Ottieni richieste pendenti (per il conducente)
 * @route   GET /api/trasporti/requests/pending
 * @access  Private
 */
const getPendingRequests = async (req, res) => {
  try {
    const userId = req.user._id;
    const { idapp } = req.query;

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

    const requests = await RideRequest.find({
      idapp,
      driverId: userId,
      status: 'pending',
    })
      .populate('passengerId', 'username name surname profile.img profile.driverProfile.averageRating')
      .populate('rideId', 'departure destination dateTime passengers')
      .sort({ createdAt: -1 });

    res.json({
      success: true,
      data: requests,
      total: requests.length,
    });
  } catch (error) {
    console.error('Errore recupero richieste pendenti:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero delle richieste pendenti',
      error: error.message,
    });
  }
};

/**
 * @desc    Accetta una richiesta di passaggio
 * @route   PUT /api/trasporti/requests/:id/accept
 * @access  Private (solo conducente)
 */
const acceptRequest = async (req, res) => {
  try {
    const { id } = req.params;
    const { responseMessage, idapp } = req.body;
    const userId = req.user._id;

    const request = await RideRequest.findById(id).populate('rideId');

    if (!request) {
      return res.status(404).json({
        success: false,
        message: 'Richiesta non trovata',
      });
    }

    // Verifica che sia il conducente
    if (request.driverId.toString() !== userId.toString()) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato ad accettare questa richiesta',
      });
    }

    // Verifica che sia ancora pendente
    if (request.status !== 'pending') {
      return res.status(400).json({
        success: false,
        message: `La richiesta è già stata ${request.status}`,
      });
    }

    // Verifica disponibilità posti
    const ride = request.rideId;
    if (ride.passengers.available < request.seatsRequested) {
      return res.status(400).json({
        success: false,
        message: 'Posti non più disponibili',
      });
    }

    // Accetta la richiesta
    request.status = 'accepted';
    request.responseMessage = responseMessage || '';
    request.respondedAt = new Date();
    await request.save();

    // Aggiorna il ride con il passeggero
    ride.confirmedPassengers.push({
      userId: request.passengerId,
      seats: request.seatsRequested,
      pickupPoint: request.pickupPoint || ride.departure,
      dropoffPoint: request.dropoffPoint || ride.destination,
      confirmedAt: new Date(),
    });
    await ride.updateAvailableSeats();

    // Invia messaggio nella chat
    const chat = await Chat.findOrCreateDirect(idapp, userId, request.passengerId, ride._id);
    const chatMessage = new Message({
      idapp,
      chatId: chat._id,
      senderId: userId,
      text: responseMessage || '✅ Richiesta accettata! Ci vediamo al punto di partenza.',
      type: 'ride_accepted',
      metadata: {
        rideId: ride._id,
        rideRequestId: request._id,
      },
    });
    await chatMessage.save();

    // TODO: Inviare notifica push al passeggero

    await request.populate('passengerId', 'username name surname profile.img');
    await request.populate('rideId', 'departure destination dateTime');

    res.json({
      success: true,
      message: 'Richiesta accettata!',
      data: request,
    });
  } catch (error) {
    console.error('Errore accettazione richiesta:', error);
    res.status(500).json({
      success: false,
      message: "Errore nell'accettazione della richiesta",
      error: error.message,
    });
  }
};

/**
 * @desc    Rifiuta una richiesta di passaggio
 * @route   PUT /api/trasporti/requests/:id/reject
 * @access  Private (solo conducente)
 */
const rejectRequest = async (req, res) => {
  try {
    const { id } = req.params;
    const { responseMessage, idapp } = req.body;
    const userId = req.user._id;

    const request = await RideRequest.findById(id);

    if (!request) {
      return res.status(404).json({
        success: false,
        message: 'Richiesta non trovata',
      });
    }

    // Verifica che sia il conducente
    if (request.driverId.toString() !== userId.toString()) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato',
      });
    }

    // Verifica che sia ancora pendente
    if (request.status !== 'pending') {
      return res.status(400).json({
        success: false,
        message: `La richiesta è già stata ${request.status}`,
      });
    }

    // Rifiuta la richiesta
    request.status = 'rejected';
    request.responseMessage = responseMessage || '';
    request.respondedAt = new Date();
    await request.save();

    // Invia messaggio nella chat
    const chat = await Chat.findOrCreateDirect(idapp, userId, request.passengerId, request.rideId);
    const chatMessage = new Message({
      idapp,
      chatId: chat._id,
      senderId: userId,
      text: responseMessage || '❌ Mi dispiace, non posso accettare questa richiesta.',
      type: 'ride_rejected',
      metadata: {
        rideId: request.rideId,
        rideRequestId: request._id,
      },
    });
    await chatMessage.save();

    // TODO: Inviare notifica push al passeggero

    res.json({
      success: true,
      message: 'Richiesta rifiutata',
      data: request,
    });
  } catch (error) {
    console.error('Errore rifiuto richiesta:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel rifiuto della richiesta',
      error: error.message,
    });
  }
};

/**
 * @desc    Cancella una richiesta (dal passeggero)
 * @route   PUT /api/trasporti/requests/:id/cancel
 * @access  Private
 */
const cancelRequest = async (req, res) => {
  try {
    const { id } = req.params;
    const { reason } = req.body;
    const userId = req.user._id;

    const request = await RideRequest.findById(id);

    if (!request) {
      return res.status(404).json({
        success: false,
        message: 'Richiesta non trovata',
      });
    }

    // Verifica che sia il passeggero o il conducente
    const isPassenger = request.passengerId.toString() === userId.toString();
    const isDriver = request.driverId.toString() === userId.toString();

    if (!isPassenger && !isDriver) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato',
      });
    }

    // Verifica che possa essere cancellata
    if (!['pending', 'accepted'].includes(request.status)) {
      return res.status(400).json({
        success: false,
        message: 'Questa richiesta non può essere cancellata',
      });
    }

    // Se era accettata, rimuovi il passeggero dal ride
    if (request.status === 'accepted') {
      const ride = await Ride.findById(request.rideId);
      if (ride) {
        ride.confirmedPassengers = ride.confirmedPassengers.filter(
          (p) => p.userId.toString() !== request.passengerId.toString()
        );
        await ride.updateAvailableSeats();
      }
    }

    request.status = 'cancelled';
    request.cancelledBy = isPassenger ? 'passenger' : 'driver';
    request.cancellationReason = reason || '';
    request.cancelledAt = new Date();
    await request.save();

    // TODO: Inviare notifica all'altra parte

    res.json({
      success: true,
      message: 'Richiesta cancellata',
      data: request,
    });
  } catch (error) {
    console.error('Errore cancellazione richiesta:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nella cancellazione',
      error: error.message,
    });
  }
};

/**
 * @desc    Ottieni una singola richiesta
 * @route   GET /api/trasporti/requests/:id
 * @access  Private
 */
const getRequestById = async (req, res) => {
  try {
    const { id } = req.params;
    const userId = req.user._id;

    const request = await RideRequest.findById(id)
      .populate('passengerId', 'username name surname profile.img profile.Cell profile.driverProfile')
      .populate('driverId', 'username name surname profile.img profile.Cell profile.driverProfile')
      .populate({
        path: 'rideId',
        populate: {
          path: 'userId',
          select: 'username name surname profile.img',
        },
      })
      .populate('contribution.contribTypeId', 'label icon color');

    if (!request) {
      return res.status(404).json({
        success: false,
        message: 'Richiesta non trovata',
      });
    }

    // Verifica che l'utente sia coinvolto
    const isPassenger = request.passengerId._id.toString() === userId.toString();
    const isDriver = request.driverId._id.toString() === userId.toString();

    if (!isPassenger && !isDriver) {
      return res.status(403).json({
        success: false,
        message: 'Non sei autorizzato a vedere questa richiesta',
      });
    }

    res.json({
      success: true,
      data: request,
    });
  } catch (error) {
    console.error('Errore recupero richiesta:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero della richiesta',
      error: error.message,
    });
  }
};

/**
 * @desc    Ottieni richieste ricevute (io come conducente)
 * @route   GET /api/trasporti/requests/received
 * @access  Private
 */
const getReceivedRequests = async (req, res) => {
  try {
    const driverId = req.user._id;
    const { status, page = 1, limit = 20 } = req.query;

    // Build query
    const query = { driverId };
    if (status) {
      query.status = status;
    }

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

    // Fetch requests
    const requests = await RideRequest.find(query)
      .populate('passengerId', 'name surname profile.img')  // <-- FIX: passengerId invece di userId
      .populate('rideId', 'departure destination departureDate availableSeats')
      .sort({ createdAt: -1 })
      .skip(skip)
      .limit(parseInt(limit))
      .lean();

    // Get counts by status
    const counts = await RideRequest.aggregate([
      { $match: { driverId } },
      {
        $group: {
          _id: '$status',
          count: { $sum: 1 }
        }
      }
    ]);

    // Format counts
    const statusCounts = {
      pending: 0,
      accepted: 0,
      rejected: 0,
      cancelled: 0,
      expired: 0,
      completed: 0
    };

    counts.forEach(c => {
      if (statusCounts.hasOwnProperty(c._id)) {
        statusCounts[c._id] = c.count;
      }
    });

    // Total count
    const total = await RideRequest.countDocuments(query);

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

  } catch (error) {
    console.error('Error fetching received requests:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero delle richieste ricevute',
      error: error.message
    });
  }
};
/**
 * @desc    Ottieni richieste inviate (io come passeggero)
 * @route   GET /api/trasporti/requests/sent
 * @access  Private
 */
const getSentRequests = async (req, res) => {
  try {
    const userId = req.user._id;
    const { status, page = 1, limit = 20 } = req.query;

    // Build query - FIX: usa passengerId invece di userId
    const query = { passengerId: userId };
    if (status) {
      query.status = status;
    }

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

    // Fetch requests
    const requests = await RideRequest.find(query)
      .populate('driverId', 'name surname profile.img')
      .populate('rideId', 'departure destination departureDate availableSeats currentPassengers')
      .sort({ createdAt: -1 })
      .skip(skip)
      .limit(parseInt(limit))
      .lean();

    // Enrich with ride info
    const enrichedRequests = requests.map(request => {
      const req = { ...request };
      
      // Add ride info if rideId is populated
      if (req.rideId) {
        req.rideInfo = {
          departure: req.rideId.departure?.city || req.rideId.departure,
          destination: req.rideId.destination?.city || req.rideId.destination,
          departureDate: req.rideId.departureDate,
          availableSeats: req.rideId.availableSeats,
          currentPassengers: req.rideId.currentPassengers || 0
        };
      }

      return req;
    });

    // Total count
    const total = await RideRequest.countDocuments(query);

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

  } catch (error) {
    console.error('Error fetching sent requests:', error);
    res.status(500).json({
      success: false,
      message: 'Errore nel recupero delle richieste inviate',
      error: error.message
    });
  }
};

module.exports = {
  createRequest,
  getRequestsForRide,
  getMyRequests,
  getPendingRequests,
  acceptRequest,
  rejectRequest,
  cancelRequest,
  getRequestById,
  getReceivedRequests,
  getSentRequests,
};
