const { Op } = require('sequelize');
const { BusSchedules, Members, Routes, Drivers } = require('../../models');
const { Rides } = require('../../models');
const { formatCase } = require('../../util/formatter');

exports.scan = async (req, res, next) => {
	try {
		const { type, qr } = req.body;
		const { driverId } = req;

		const driver = await Drivers.findOne({
			where: { id: driverId },
			attributes: ['id', 'shuttle_number'],
		});

		const activeSchedule = await BusSchedules.findOne({
			where: {
				driver_id: driverId,
				start_time: { [Op.ne]: null },
				finish_time: null,
			},
			include: {
				model: Routes,
				as: 'route',
				attributes: ['from', 'to', 'direction'],
			},
		});

		if (!activeSchedule) {
			return res.status(404).json({ success: false, message: 'No active schedule found.' });
		}

		const member = await Members.findOne({
			where: { id: qr },
			attributes: ['id', 'account_id', 'first_name', 'middle_name', 'last_name', 'email_address'],
		});

		if (!member) {
			return res.status(404).json({ success: false, message: 'Member not found.' });
		}

		if (type === 'onboarding') {
			const existingRide = await Rides.findOne({
				where: {
					member_id: member.id,
					driver_id: driverId,
					driver_route_id: activeSchedule.id,
					status: 'Ongoing',
				},
			});

			if (existingRide) {
				return res.status(400).json({ success: false, message: 'Member is already onboarded.' });
			}

			const ride = await Rides.create({
				member_id: member.id,
				driver_id: driverId,
				driver_route_id: activeSchedule.id,
				status: 'Ongoing',
				start_location: activeSchedule.route.from,
				end_location: activeSchedule.route.to,
				direction: activeSchedule.route.direction,
				bus_number: driver.shuttle_number,
				date: new Date(),
				onboard_at: new Date(),
			});

			return res
				.status(200)
				.json({ success: true, message: 'Onboarding successful.', member: formatCase(member), ride: formatCase(ride) });
		}

		if (type === 'offboarding') {
			const ride = await Rides.findOne({
				where: {
					member_id: member.id,
					driver_id: driverId,
					driver_route_id: activeSchedule.id,
					status: 'Ongoing',
				},
			});

			if (!ride) {
				return res.status(404).json({ success: false, message: 'No ongoing ride found for offboarding.' });
			}

			ride.status = 'Completed';
			ride.offboard_at = new Date();
			await ride.save();

			return res.status(200).json({
				success: true,
				message: 'Offboarding successful.',
				member: formatCase(member),
				ride: formatCase(ride),
			});
		}

		return res.status(400).json({ success: false, message: 'Invalid type.' });
	} catch (error) {
		next(error);
	}
};

exports.list = async (req, res, next) => {
	try {
		const { driverId } = req;
		const { routeId } = req.query;
		let driverRoute;

		if (routeId) {
			driverRoute = await BusSchedules.findOne({
				where: { id: routeId, driver_id: driverId },
			});
		} else {
			driverRoute = await BusSchedules.findOne({
				where: {
					driver_id: driverId,
					start_time: { [Op.ne]: null },
					finish_time: null,
				},
				include: {
					model: Routes,
					as: 'route',
					attributes: ['from', 'to', 'direction'],
				},
			});
		}
		if (!driverRoute) {
			return res.status(404).json({ success: false, message: 'No active driver route found.' });
		}

		let list = await Rides.findAll({
			where: {
				driver_id: driverId,
				driver_route_id: driverRoute.id,
			},
			attributes: ['id', 'onboard_at', 'offboard_at'],
			include: [
				{
					model: Members,
					as: 'member',
					attributes: ['id', 'first_name', 'last_name', 'account_id'],
				},
			],
			order: [['createdAt', 'DESC']],
		});

		list = list.map((item) => {
			let ride = item.get({ plain: true });
			delete ride.member.id;
			ride = {
				...ride,
				...ride.member,
			};
			delete ride.member;

			return formatCase(ride);
		});

		return res.status(200).json({ success: true, data: list, route: formatCase(driverRoute.get({ plain: true })) });
	} catch (error) {
		next(error);
	}
};
