const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Schema per le coordinate geografiche
const CoordinatesSchema = new Schema(
  {
    lat: {
      type: Number,
      required: true,
    },
    lng: {
      type: Number,
      required: true,
    },
  },
  { _id: false }
);

// Schema per una località (partenza, destinazione, waypoint)
const LocationSchema = new Schema(
  {
    city: {
      type: String,
      required: true,
      trim: true,
    },
    address: {
      type: String,
      trim: true,
    },
    province: {
      type: String,
      trim: true,
    },
    region: {
      type: String,
      trim: true,
    },
    country: {
      type: String,
      default: 'Italia',
      trim: true,
    },
    postalCode: {
      type: String,
      trim: true,
    },
    coordinates: {
      type: CoordinatesSchema,
      required: true,
    },
  },
  { _id: false }
);

// Schema per i waypoint (tappe intermedie)
const WaypointSchema = new Schema({
  location: {
    type: LocationSchema,
    required: true,
  },
  order: {
    type: Number,
    required: true,
  },
  estimatedArrival: {
    type: Date,
  },
  stopDuration: {
    type: Number, // minuti di sosta
    default: 0,
  },
});

// Schema per la ricorrenza del viaggio
const RecurrenceSchema = new Schema(
  {
    type: {
      type: String,
      enum: ['once', 'weekly', 'custom_days', 'custom_dates'],
      default: 'once',
    },
    daysOfWeek: [
      {
        type: Number,
        min: 0,
        max: 6,
        // 0 = Domenica, 1 = Lunedì, ..., 6 = Sabato
      },
    ],
    customDates: [
      {
        type: Date,
      },
    ],
    startDate: {
      type: Date,
    },
    endDate: {
      type: Date,
    },
    excludedDates: [
      {
        type: Date,
      },
    ],
  },
  { _id: false }
);

// Schema per i passeggeri
const PassengersSchema = new Schema(
  {
    available: {
      type: Number,
      required: true,
      min: 0,
    },
    max: {
      type: Number,
      required: true,
      min: 1,
    },
  },
  { _id: false }
);

// Schema per il veicolo
const VehicleSchema = new Schema(
  {
    type: {
      type: String,
      enum: ['auto', 'moto', 'furgone', 'minibus', 'altro'],
      default: 'auto',
    },
    brand: {
      type: String,
      trim: true,
    },
    model: {
      type: String,
      trim: true,
    },
    color: {
      type: String,
      trim: true,
    },
    colorHex: {
      type: String,
      trim: true,
    },
    year: {
      type: Number,
    },
    licensePlate: {
      type: String,
      trim: true,
    },
    seats: {
      type: Number,
      min: 1,
    },
    photos: [
      {
        type: String,
        trim: true,
      },
    ],
    features: [
      {
        type: String,
        enum: ['aria_condizionata', 'wifi', 'presa_usb', 'bluetooth', 'bagagliaio_grande', 'seggiolino_bimbi'],
      },
    ],
  },
  { _id: false }
);

// Schema per le preferenze di viaggio
const RidePreferencesSchema = new Schema(
  {
    smoking: {
      type: String,
      enum: ['yes', 'no', 'outside_only'],
      default: 'no',
    },
    pets: {
      type: String,
      enum: ['no', 'small', 'medium', 'large', 'all'],
      default: 'no',
    },
    luggage: {
      type: String,
      enum: ['none', 'small', 'medium', 'large'],
      default: 'medium',
    },
    packages: {
      type: Boolean,
      default: false,
    },
    maxPackageSize: {
      type: String,
      enum: ['small', 'medium', 'large', 'xlarge'],
      default: 'medium',
    },
    music: {
      type: String,
      enum: ['no_music', 'quiet', 'moderate', 'loud', 'passenger_choice'],
      default: 'moderate',
    },
    conversation: {
      type: String,
      enum: ['quiet', 'moderate', 'chatty'],
      default: 'moderate',
    },
    foodAllowed: {
      type: Boolean,
      default: true,
    },
    childrenFriendly: {
      type: Boolean,
      default: true,
    },
    wheelchairAccessible: {
      type: Boolean,
      default: false,
    },
    otherPreferences: {
      type: String,
      trim: true,
      maxlength: 500,
    },
  },
  { _id: false }
);

// Schema per il contributo/pagamento
const ContributionItemSchema = new Schema({
  contribTypeId: {
    type: Schema.Types.ObjectId,
    ref: 'Contribtype',
    required: true,
  },
  price: {
    type: Number,
    min: 0,
  },
  pricePerKm: {
    type: Number,
    min: 0,
  },
  notes: {
    type: String,
    trim: true,
  },
});

const ContributionSchema = new Schema(
  {
    contribTypes: [ContributionItemSchema],
    negotiable: {
      type: Boolean,
      default: true,
    },
    freeForStudents: {
      type: Boolean,
      default: false,
    },
    freeForElders: {
      type: Boolean,
      default: false,
    },
  },
  { _id: false }
);

// Schema principale del Ride
const RideSchema = new Schema(
  {
    idapp: {
      type: String,
      required: true,
      index: true,
    },
    userId: {
      type: Schema.Types.ObjectId,
      ref: 'User',
      required: true,
      index: true,
    },
    type: {
      type: String,
      enum: ['offer', 'request'],
      required: true,
      index: true,
      // offer = 🟢 Offerta passaggio (sono conducente)
      // request = 🔴 Richiesta passaggio (cerco passaggio)
    },
    departure: {
      type: LocationSchema,
      required: true,
    },
    destination: {
      type: LocationSchema,
      required: true,
    },
    waypoints: [WaypointSchema],
    dateTime: {
      type: Date,
      required: true,
      index: true,
    },
    flexibleTime: {
      type: Boolean,
      default: false,
    },
    flexibleMinutes: {
      type: Number,
      default: 30,
      min: 0,
      max: 180,
    },
    recurrence: {
      type: RecurrenceSchema,
      default: () => ({ type: 'once' }),
    },
    passengers: {
      type: PassengersSchema,
      required: function () {
        return this.type === 'offer';
      },
    },
    seatsNeeded: {
      type: Number,
      min: 1,
      default: 1,
      // Solo per type = 'request'
    },
    vehicle: {
      type: VehicleSchema,
      required: function () {
        return this.type === 'offer';
      },
    },
    preferences: {
      type: RidePreferencesSchema,
      default: () => ({}),
    },
    contribution: {
      type: ContributionSchema,
      default: () => ({ contribTypes: [] }),
    },
    status: {
      type: String,
      enum: ['draft', 'active', 'full', 'in_progress', 'completed', 'cancelled', 'expired'],
      default: 'active',
      index: true,
    },
    estimatedDistance: {
      type: Number, // in km
      min: 0,
    },
    estimatedDuration: {
      type: Number, // in minuti
      min: 0,
    },
    routePolyline: {
      type: String, // Polyline encoded per visualizzare il percorso
    },
    confirmedPassengers: [
      {
        userId: {
          type: Schema.Types.ObjectId,
          ref: 'User',
        },
        seats: {
          type: Number,
          default: 1,
        },
        pickupPoint: LocationSchema,
        dropoffPoint: LocationSchema,
        confirmedAt: {
          type: Date,
          default: Date.now,
        },
      },
    ],
    views: {
      type: Number,
      default: 0,
    },
    isFeatured: {
      type: Boolean,
      default: false,
    },
    notes: {
      type: String,
      trim: true,
      maxlength: 1000,
    },
    cancellationReason: {
      type: String,
      trim: true,
    },
    cancelledAt: {
      type: Date,
    },
  },
  {
    timestamps: true,
    toJSON: { virtuals: true },
    toObject: { virtuals: true },
  }
);

// Indici per ricerche ottimizzate
RideSchema.index({ 'departure.city': 1, 'destination.city': 1 });
RideSchema.index({ 'departure.coordinates': '2dsphere' });
RideSchema.index({ 'destination.coordinates': '2dsphere' });
RideSchema.index({ 'waypoints.location.city': 1 });
RideSchema.index({ dateTime: 1, status: 1 });
RideSchema.index({ idapp: 1, status: 1, dateTime: 1 });

// Virtual per verificare se il viaggio è pieno
RideSchema.virtual('isFull').get(function () {
  if (this.type === 'request') return false;
  // ⚠️ CONTROLLO: verifica che passengers esista
  if (!this.passengers || typeof this.passengers.available === 'undefined') return false;
  return this.passengers.available <= 0;
});

// Virtual per calcolare posti occupati
RideSchema.virtual('bookedSeats').get(function () {
  if (!this.confirmedPassengers) return 0;
  return this.confirmedPassengers.reduce((sum, p) => sum + (p.seats || 1), 0);
});

// Virtual per ottenere tutte le città del percorso
RideSchema.virtual('allCities').get(function () {
  const cities = [this.departure.city];
  if (this.waypoints && this.waypoints.length > 0) {
    this.waypoints.sort((a, b) => a.order - b.order).forEach((wp) => cities.push(wp.location.city));
  }
  cities.push(this.destination.city);
  return cities;
});

// Metodo per verificare se passa per una città
RideSchema.methods.passesThrough = function (cityName) {
  const normalizedCity = cityName.toLowerCase().trim();
  return this.allCities.some(
    (city) => city.toLowerCase().trim().includes(normalizedCity) || normalizedCity.includes(city.toLowerCase().trim())
  );
};

// Metodo per aggiornare posti disponibili
RideSchema.methods.updateAvailableSeats = function () {
  // ⚠️ CONTROLLO: verifica che sia un'offerta e che passengers esista
  if (this.type === 'offer' && this.passengers) {
    const booked = this.bookedSeats;
    this.passengers.available = this.passengers.max - booked;
    if (this.passengers.available <= 0) {
      this.status = 'full';
    } else if (this.status === 'full') {
      this.status = 'active';
    }
  }
  return this.save();
};

// Pre-save hook
RideSchema.pre('save', function (next) {
  // ⚠️ CONTROLLO: Aggiorna posti disponibili solo se è un'offerta e passengers esiste
  if (this.type === 'offer' && this.passengers && this.isModified('confirmedPassengers')) {
    const booked = this.confirmedPassengers.reduce((sum, p) => sum + (p.seats || 1), 0);
    this.passengers.available = this.passengers.max - booked;
    if (this.passengers.available <= 0) {
      this.status = 'full';
    }
  }
  next();
});

// Metodi statici per ricerche comuni
RideSchema.statics.findActiveByCity = function (idapp, departureCity, destinationCity, options = {}) {
  const query = {
    idapp,
    status: { $in: ['active', 'full'] },
    dateTime: { $gte: new Date() },
  };

  if (departureCity) {
    query['departure.city'] = new RegExp(departureCity, 'i');
  }
  if (destinationCity) {
    query['destination.city'] = new RegExp(destinationCity, 'i');
  }
  if (options.type) {
    query.type = options.type;
  }
  if (options.date) {
    const startOfDay = new Date(options.date);
    startOfDay.setHours(0, 0, 0, 0);
    const endOfDay = new Date(options.date);
    endOfDay.setHours(23, 59, 59, 999);
    query.dateTime = { $gte: startOfDay, $lte: endOfDay };
  }

  return this.find(query)
    .populate('userId', 'username name surname profile.driverProfile.averageRating')
    .sort({ dateTime: 1 });
};

// Ricerca viaggi che passano per una città intermedia
RideSchema.statics.findPassingThrough = function (idapp, cityName, options = {}) {
  const cityRegex = new RegExp(cityName, 'i');
  const query = {
    idapp,
    status: { $in: ['active'] },
    dateTime: { $gte: new Date() },
    $or: [{ 'departure.city': cityRegex }, { 'destination.city': cityRegex }, { 'waypoints.location.city': cityRegex }],
  };

  if (options.type) {
    query.type = options.type;
  }

  return this.find(query)
    .populate('userId', 'username name surname profile.driverProfile.averageRating')
    .sort({ dateTime: 1 });
};

const Ride = mongoose.model('Ride', RideSchema);

module.exports = Ride;