const { Rides, Members, Drivers, Buses, sequelize } = require('../../models');
const { errorHandler } = require('../../util');
const { formatCase } = require('../../util/formatter');
const { Op } = require('sequelize');
exports.createRide = async (req, res, next) => {
	let transaction = await sequelize.transaction();
	try {
		const { member_id, driver_id, bus_id, start_location, end_location, type } = req.body;

		if (!member_id || !driver_id || !bus_id || !start_location || !end_location) {
			return errorHandler('Member ID, Driver ID, Bus ID, start location, and end location are required', 400);
		}

		const member = await Members.findByPk(member_id);
		if (!member) {
			return errorHandler('Member not found', 404);
		}

		const driver = await Drivers.findByPk(driver_id);
		if (!driver) {
			return errorHandler('Driver not found', 404);
		}

		const bus = await Buses.findByPk(bus_id);
		if (!bus) {
			return errorHandler('Bus not found', 404);
		}

		let ride;
		if (type === 'out') {
			ride = await Rides.findOne({
				where: {
					member_id,
					driver_id,
					bus_id,
					start_location,
					end_location,
					status: 'Ongoing',
					createdAt: {
						[Op.gte]: new Date(Date.now() - 24 * 60 * 60 * 1000),
					},
				},
			});

			if (ride) {
				await ride.update({ status: 'Completed' }, { transaction });
				await transaction.commit();

				ride = await Rides.findByPk(ride.id, {
					include: [
						{
							model: Members,
							as: 'member',
							attributes: ['id', 'first_name', 'last_name'],
						},
						{
							model: Drivers,
							as: 'driver',
							attributes: ['id', 'first_name', 'last_name'],
						},
						{
							model: Buses,
							as: 'bus',
							attributes: ['id', 'bus_number'],
						},
					],
				});

				return res.status(200).json({
					success: true,
					message: 'Ride status updated to completed',
					data: formatCase(ride.get({ plain: true })),
				});
			}
		}

		ride = await Rides.create(
			{
				member_id,
				driver_id,
				bus_id,
				start_location,
				end_location,
				status: 'Ongoing',
			},
			{ transaction },
		);

		await transaction.commit();
		transaction = null;

		ride = await Rides.findByPk(ride.id, {
			include: [
				{
					model: Members,
					as: 'member',
					attributes: ['id', 'first_name', 'last_name'],
				},
				{
					model: Drivers,
					as: 'driver',
					attributes: ['id', 'first_name', 'last_name'],
				},
				{
					model: Buses,
					as: 'bus',
					attributes: ['id', 'bus_number'],
				},
			],
		});

		return res.status(201).json({
			success: true,
			message: 'Ride created successfully',
			data: formatCase(ride.get({ plain: true })),
		});
	} catch (error) {
		if (transaction) await transaction.rollback();
		next(error);
	}
};

exports.getAllRides = async (req, res, next) => {
	try {
		const { page = 1, limit = 10, status } = req.query;
		const offset = (parseInt(page) - 1) * parseInt(limit);

		let whereClause = {};
		if (status) {
			whereClause.status = status;
		}

		const { count, rows: rides } = await Rides.findAndCountAll({
			where: whereClause,
			include: [
				{
					model: Members,
					as: 'member',
					attributes: ['id', 'first_name', 'last_name', 'email'],
				},
				{
					model: Drivers,
					as: 'driver',
					attributes: ['id', 'first_name', 'last_name', 'license_number'],
				},
				{
					model: Buses,
					as: 'bus',
					attributes: ['id', 'bus_number', 'capacity'],
				},
			],
			order: [['createdAt', 'DESC']],
			limit: parseInt(limit),
			offset: offset,
		});

		return res.status(200).json({
			success: true,
			data: {
				rides: formatCase(rides.map((ride) => ride.get({ plain: true }))),
				pagination: {
					currentPage: parseInt(page),
					totalPages: Math.ceil(count / parseInt(limit)),
					totalItems: count,
					itemsPerPage: parseInt(limit),
				},
			},
		});
	} catch (error) {
		next(error);
	}
};
