const mongoose = require('mongoose');
const Trip = require('../models/travlr'); // Register model
const Model = mongoose.model('trips');
const asyncHandler = require('../middleware/asyncHandler');
const { ApiError } = require('../middleware/errorHandler');

// Every controller is wrapped in asyncHandler, so rejected promises
// and thrown ApiErrors flow to the centralized error-handling
// middleware. This removes the duplicated if(!q) blocks that
// previously referenced an undefined `err` variable and returned
// inconsistent status codes.

// GET: /trips - lists all the trips
const tripsList = asyncHandler(async (req, res) => {
    const trips = await Model
        .find({}) // No filter, return all records
        .exec();
    return res.status(200).json(trips);
});

// GET: /trips/:tripCode - lists a single trip
const tripsFindByCode = asyncHandler(async (req, res) => {
    const trips = await Model
        .find({ 'code': req.params.tripCode })
        .exec();
    if (!trips || trips.length === 0) {
        throw new ApiError(404, `Trip '${req.params.tripCode}' not found`);
    }
    return res.status(200).json(trips);
});

// POST: /trips - Adds a new Trip (JWT protected)
const tripsAddTrip = asyncHandler(async (req, res) => {
    const newTrip = new Trip({
        code: req.body.code,
        name: req.body.name,
        length: req.body.length,
        start: req.body.start,
        resort: req.body.resort,
        perPerson: req.body.perPerson,
        image: req.body.image,
        description: req.body.description
    });
    // A Mongoose ValidationError thrown here is translated to a 400
    // by the centralized error handler.
    const savedTrip = await newTrip.save();
    return res.status(201).json(savedTrip);
});

// PUT: /trips/:tripCode - Updates an existing Trip (JWT protected)
const tripsUpdateTrip = asyncHandler(async (req, res) => {
    const updatedTrip = await Model
        .findOneAndUpdate(
            { 'code': req.params.tripCode },
            {
                code: req.body.code,
                name: req.body.name,
                length: req.body.length,
                start: req.body.start,
                resort: req.body.resort,
                perPerson: req.body.perPerson,
                image: req.body.image,
                description: req.body.description
            },
            { new: true, runValidators: true }
        )
        .exec();
    if (!updatedTrip) {
        throw new ApiError(404, `Trip '${req.params.tripCode}' not found`);
    }
    return res.status(200).json(updatedTrip);
});

// DELETE: /trips/:tripCode - Removes a Trip (JWT protected)
const tripsDeleteTrip = asyncHandler(async (req, res) => {
    const deletedTrip = await Model
        .findOneAndDelete({ 'code': req.params.tripCode })
        .exec();
    if (!deletedTrip) {
        throw new ApiError(404, `Trip '${req.params.tripCode}' not found`);
    }
    return res.status(204).send();
});

module.exports = {
    tripsList,
    tripsFindByCode,
    tripsAddTrip,
    tripsUpdateTrip,
    tripsDeleteTrip
};
