const { Op } = require('sequelize');
const { parseJsonSafe } = require('../../helpers');
const { HostRegistrationFiles, HostsRegistrations } = require('../../models');
const {
	createHostRegistration,
	updateUserStatus,
	checkUserStatus,
	findHostRegistrationById,
	approveHostRegistration,
	createListing,
	saveListingImages,
	updateUserHostStatus,
	createListingAddOns,
} = require('../../services');
const { errorHandler } = require('../../util');

exports.applyHost = (req, res, next) => {
	const { userId } = req;
	const { data } = req.body;

	checkUserStatus(userId)
		.then(() => {
			return createHostRegistration(userId, data, req.files);
		})
		.then((newUser) => {
			return updateUserStatus(userId).then(() => newUser);
		})
		.then(() => {
			return res.status(201).json({ success: true });
		})
		.catch((err) => {
			next(err);
		});
};

exports.getMyApplications = (req, res, next) => {
	const { userId } = req;
	const { status, search } = req.query;

	const filter = {
		user_id: userId,
		status: { [Op.ne]: 'Approved' },
	};

	if (status && status !== 'Approved') {
		filter.status = status;
	}

	if (search) {
		filter[Op.or] = [
			{ listing_name: { [Op.like]: `%${search}%` } },
			{ listing_description: { [Op.like]: `%${search}%` } },
			{ location_address: { [Op.like]: `%${search}%` } },
		];
	}

	HostsRegistrations.findAll({
		where: filter,
		include: [
			{
				model: HostRegistrationFiles,
				as: 'files',
				where: { file_type: 'Listing Images' },
				limit: 1,
				attributes: ['file_type', 'file'],
			},
		],
	})
		.then((applications) => {
			const mappedData = applications.map((application) => ({
				id: application.id,
				listingName: application.listing_name,
				description: application.listing_description,
				location: application.location_address,
				status: application.status,
				image: application.files
					? application.files.map((file) => ({
							fileType: file.file_type,
							file: `${process.env.BASE_URL}/public/host-uploads/${file.file}`,
						}))
					: [],
			}));

			return res.status(200).json({
				success: true,
				data: mappedData,
			});
		})
		.catch((err) => {
			next(err);
		});
};

exports.approveApplication = (req, res, next) => {
	const { applicationId } = req.params;

	findHostRegistrationById(applicationId)
		.then((hostRegistration) => {
			if (!hostRegistration) {
				return errorHandler('Application not found.', 404);
			}

			if (hostRegistration.status === 'Approved') {
				return errorHandler('Application has already been approved.', 400);
			}

			return approveHostRegistration(applicationId)
				.then(() =>
					createListing({
						host_id: hostRegistration.user_id,
						name: hostRegistration.listing_name,
						description: hostRegistration.listing_description,
						location_type: JSON.parse(hostRegistration.location_type),
						address_country: hostRegistration.address_country,
						address_street: hostRegistration.address_street,
						address_apt: hostRegistration.address_apt,
						address_city: hostRegistration.address_city,
						address_state: hostRegistration.address_state,
						address_zip: hostRegistration.address_zip,
						longitude: hostRegistration.location_long,
						latitude: hostRegistration.location_lat,
						price: hostRegistration.individual_rate,
						min_capacity: 1,
						max_capacity: hostRegistration.capacity,
						amenities: JSON.parse(hostRegistration.amenities),
						services: JSON.parse(hostRegistration.services),
						check_in_time: hostRegistration.check_in_time,
						check_out_time: hostRegistration.check_out_time,
						cancellation_policy: hostRegistration.cancellation_policy,
					}),
				)
				.then((listing) => saveListingImages(listing.id, hostRegistration.files).then(() => listing))
				.then((listing) => createListingAddOns(listing.id, hostRegistration.id))
				.then(() => updateUserHostStatus(hostRegistration.user_id));
		})
		.then(() => {
			res.status(200).json({
				success: true,
				message: 'Application has been approved successfully.',
			});
		})
		.catch((err) => {
			next(err);
		});
};

exports.getApplicationById = (req, res, next) => {
	const { userId } = req;
	const { applicationId } = req.params;

	const filter = {
		user_id: userId,
		id: applicationId,
	};

	HostsRegistrations.findOne({
		where: filter,
		include: [
			{
				model: HostRegistrationFiles,
				as: 'files',
				attributes: ['file_type', 'file'],
			},
		],
	})
		.then((application) => {
			if (!application) {
				return res.status(404).json({
					success: false,
					message: 'Application not found',
				});
			}

			const mappedData = {
				application: {
					id: application.id,
					cityToHost: application.city_to_hosts,
					listingName: application.listing_name,
					description: application.listing_description,
					duration: application.duration,
					location: {
						type: parseJsonSafe(application.location_type),
						address: application.location_address,
						lat: application.location_lat,
						long: application.location_long,
					},
					amenities: parseJsonSafe(application.amenities),
					services: parseJsonSafe(application.services),
					checkInTime: application.check_in_time,
					checkOutTime: application.check_out_time,
					cancellationPolicy: application.cancellation_policy,
					selfieImage: `${process.env.BASE_URL}/public/host-uploads/${application.selfie_image}`,
					status: application.status,
				},
				files: application.files
					? application.files.map((file) => ({
							fileType: file.file_type,
							file: `${process.env.BASE_URL}/public/host-uploads/${file.file}`,
						}))
					: [],
			};

			return res.status(200).json({
				success: true,
				data: mappedData,
			});
		})
		.catch((err) => {
			next(err);
		});
};
