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

exports.worldConTickets = async (req, res, next) => {
	try {
		let tickets = await WorldConTickets.findAll({
			order: [['createdAt', 'DESC']],
		});

		tickets = tickets.map((ticket) => {
			let item = ticket.get({ plain: true });
			item.image = item.image ? formatImage(item.image, 'world-con-tickets-uploads') : null;

			return item;
		});

		tickets = formatCase(tickets);

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

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

		const ticket = await WorldConTickets.findByPk(worldConTicketId);
		if (!ticket) {
			return res.status(404).json({ success: false, message: 'Ticket not found' });
		}

		const now = new Date();
		let price;

		if (ticket.registration_start && now < ticket.registration_start) {
			return res.status(400).json({ success: false, message: 'Registration has not started yet' });
		}
		if (ticket.registration_end && now > ticket.registration_end) {
			return res.status(400).json({ success: false, message: 'Registration has ended' });
		}

		if (ticket.early_bird_end && now <= ticket.early_bird_end) {
			price = ticket.early_bird_price;
		} else if (ticket.regular_end && now <= ticket.regular_end) {
			price = ticket.regular_price;
		} else if (ticket.registration_end && now <= ticket.registration_end) {
			price = ticket.late_registration_price;
		} else {
			return res.status(400).json({ success: false, message: 'No valid registration period' });
		}

		const result = await sequelize.query('SELECT MAX(CAST(ticket_no AS UNSIGNED)) as max_ticket_no FROM tickets', {
			type: sequelize.QueryTypes.SELECT,
		});
		let currentCount = result[0]?.max_ticket_no || 0;

		const createdTickets = [];
		let ticketNumber = currentCount + 1;

		for (let i = 0; i < quantity; i++) {
			let ticket_no;
			let exists = true;

			while (exists) {
				ticket_no = ticketNumber.toString().padStart(10, '0');
				const existing = await Tickets.findOne({ where: { ticket_no } });
				if (!existing) {
					exists = false;
				} else {
					ticketNumber++;
				}
			}

			const created = await Tickets.create({
				ticket_no,
				is_used: false,
				scanned_datetime: null,
				scanned_by: null,
				purchased_at: new Date(),
				purchased_by: memberId,
				worldcon_ticket_id: ticket.id,
				total: price,
				reference_no: await generateReferenceNumber(Tickets),
			});
			createdTickets.push(created);
			ticketNumber++;
		}

		await transaction.commit();

		return res.status(200).json({
			success: true,
			message: 'Tickets purchased successfully',
			data: {
				ticketId: ticket.id,
				memberId,
				price,
				quantity,
				tickets: createdTickets,
			},
		});
	} catch (error) {
		await transaction.rollback();
		next(error);
	}
};
