const { EventRegistrations, Events, sequelize } = require('../../models');
const { errorHandler } = require('../../util');
const { formatImage, formatCase } = require('../../util/formatter');
const { generateReferenceNumber } = require('../../util/reference-no');

exports.registerForEvent = async (req, res, next) => {
	const transaction = await sequelize.transaction();
	try {
		const { eventId } = req.body;
		const { memberId } = req;

		const event = await Events.findByPk(eventId);

		if (!event) {
			errorHandler('Event not found', 404);
		}

		if (event.status === 'cancelled') {
			errorHandler('Event is cancelled', 400);
		}

		const now = new Date();
		if (
			(event.registration_start && now < event.registration_start) ||
			(event.registration_end && now > event.registration_end)
		) {
			errorHandler('Registration is not open for this event', 400);
		}

		const existingRegistration = await EventRegistrations.findOne({
			where: { member_id: memberId, event_id: eventId },
		});

		if (existingRegistration) {
			errorHandler('Already registered for this event', 409);
		}

		if (event.spots_left <= 0) {
			errorHandler('No spots available for this event', 400);
		}

		const eventPrice = parseFloat(event.price);
		const totalPayment = eventPrice;

		const reference_no = await generateReferenceNumber(EventRegistrations);

		const isFreeEvent = event.event_type === 'Free';

		const registration = await EventRegistrations.create(
			{
				reference_no,
				member_id: memberId,
				event_id: eventId,
				price: isFreeEvent ? 0 : eventPrice,
				total: isFreeEvent ? 'Free' : totalPayment,
				payment_status: isFreeEvent ? 'Paid' : 'Unpaid',
				status: isFreeEvent ? 'Successful' : 'Unpaid',
			},
			{ transaction },
		);

		await event.update(
			{
				current_participants: event.current_participants + 1,
				spots_left: event.spots_left - 1,
			},
			{ transaction },
		);

		const response = {
			id: registration.id,
			referenceNo: registration.reference_no,
			event: event.organizer + ': ' + event.title,
			startDate: event.start_date,
			endDate: event.end_date,
			startTime: event.start_time,
			endTime: event.end_time,
			status: registration.status,
			total: isFreeEvent ? 'Free' : totalPayment.toFixed(2),
		};

		await transaction.commit();
		return res.status(201).json({ success: true, data: response, message: 'Successfully registered for event' });
	} catch (error) {
		await transaction.rollback();
		next(error);
	}
};

exports.payRegistration = async (req, res, next) => {
	const transaction = await sequelize.transaction();
	try {
		const { registrationId, paymentMethod, serviceFee, tax } = req.body;
		const payment = Number(req.body.payment) || 0;

		const registration = await EventRegistrations.findOne({
			where: { id: registrationId },
		});

		if (!registration) {
			return errorHandler('Registration not found or does not belong to you', 404);
		}

		if (registration.payment_status === 'Paid') {
			return errorHandler('Registration is already paid', 400);
		}

		if (registration.status === 'Successful') {
			return errorHandler('Registration is already successful', 400);
		}

		const total = Number(registration.total);
		const totalPayment = Number(registration.payment) + payment;
		let payment_status = 'Unpaid';
		if (totalPayment >= total) {
			payment_status = 'Paid';
		} else if (totalPayment !== total) {
			payment_status = 'Partially Paid';
		}

		registration.payment = Number(payment) + Number(registration.payment);
		registration.payment_status = payment_status;
		registration.payment_method = paymentMethod;
		registration.status = payment_status === 'Paid' ? 'Successful' : registration.status;
		registration.service_fee = serviceFee || 0;
		registration.tax = tax || 0;
		await registration.save({ transaction });

		await transaction.commit();

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

exports.getMyRegistrations = async (req, res, next) => {
	try {
		const { memberId } = req;
		const { status } = req.query;

		const whereClause = { member_id: memberId };
		if (status) whereClause.status = status;

		let registrations = await EventRegistrations.findAll({
			where: whereClause,
			include: [
				{
					model: Events,
					as: 'event',
				},
			],
			order: [['createdAt', 'DESC']],
		});

		registrations = registrations.map((registration) => {
			let item = registration.get({ plain: true });
			if (item.event && item.event.image) {
				item.event.image = formatImage(item.event.image, 'event-uploads');
			}
			return item;
		});

		return res.status(200).json({ success: true, data: formatCase(registrations) });
	} catch (error) {
		next(error);
	}
};

exports.getMyRegistration = async (req, res, next) => {
	try {
		const { memberId } = req;

		let registration = await EventRegistrations.findOne({
			where: { id: req.params.id, member_id: memberId },
			include: [
				{
					model: Events,
					as: 'event',
					attributes: [
						'id',
						'title',
						'description',
						'location',
						'start_date',
						'end_date',
						'start_time',
						'end_time',
						'image',
						'status',
					],
				},
			],
		});

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

		registration = registration.get({ plain: true });
		if (registration.event && registration.event.image) {
			registration.event.image = formatImage(registration.event.image, 'event-uploads');
		}

		return res.status(200).json({ success: true, data: formatCase(registration) });
	} catch (error) {
		next(error);
	}
};

// exports.cancelRegistration = async (req, res, next) => {
// 	const transaction = await sequelize.transaction();
// 	try {
// 		const { memberId } = req;

// 		const registration = await EventRegistrations.findOne({
// 			where: { id: req.params.id, member_id: memberId },
// 			include: [{ model: Events, as: 'event' }],
// 		});

// 		if (!registration) {
// 			await transaction.rollback();
// 			return res.status(404).json({ success: false, message: 'Registration not found' });
// 		}

// 		if (registration.status === 'cancelled') {
// 			await transaction.rollback();
// 			return res.status(400).json({ success: false, message: 'Registration already cancelled' });
// 		}

// 		// Update registration status
// 		await registration.update({ status: 'cancelled' }, { transaction });

// 		// Update event participant counts
// 		const event = registration.event;
// 		await event.update(
// 			{
// 				current_participants: Math.max(0, event.current_participants - 1),
// 				spots_left: event.spots_left + 1,
// 			},
// 			{ transaction },
// 		);

// 		await transaction.commit();
// 		return res.status(200).json({ success: true, message: 'Registration cancelled successfully' });
// 	} catch (error) {
// 		await transaction.rollback();
// 		next(error);
// 	}
// };
