<template>
	<div>
		<v-defaults-provider
			:defaults="{
				VTextField: {
					variant: 'outlined',
				},
				VSelect: {
					variant: 'outlined',
				},
			}"
		>
			<booking-stepper
				v-model="stepper.step"
				class="saswp-property-booking__stepper"
				v-bind="stepper"
				:contentClass="isMobile ? 'p-0' : 'p-5'"
			>
				<!-- Tab Login -->
				<template #step:login="bind">
					<!--					<LoginAndSignUp-->
					<!--						class="mt-5"-->
					<!--						@logged="logged"-->
					<!--						@next-step="() => (stepper.step = bind.next.id)"-->
					<!--					/>-->
					<div class="border-1 p-0">
						<div
							class="bg-grey-lighten-3 text-center pa-3 rounded-lg text-h6 mb-6"
							v-if="!!store.getUser"
						>
							You're logged as
							{{
								`${store.getUser.first_name ?? ""} ${
									store.getUser.last_name ?? ""
								}`
							}}.
							<v-btn variant="text" @click="store.setLogout()"
								>Logout</v-btn
							>
						</div>

						<GuestLogin
							@next-step="() => (stepper.step = bind.next.id)"
						/>
					</div>
				</template>

				<!-- Tab Payment and House Rules -->
				<template #step:reviewHouseRules&Payment="bind">
					<app-loading v-if="booking.loading" />

					<v-row
						v-if="!payment.paymentSuccess && !booking.loading"
						tag="form"
						@submit.prevent="paymentBooking"
						:class="isMobile ? 'p-4' : 'p-0'"
					>
						<v-col cols="12" sm="6">
							<v-alert
								v-if="booking.error.message"
								class="mb-3"
								type="error"
							>
								{{ booking.error.message }}
							</v-alert>

							<sas-booking-rules
								v-model="booking"
								:property="property"
								:quotes="payment.data.bookings"
							/>

							<vendor-show-lean-full
								v-if="loadingStep"
								v-model="payment.data.payment_method"
								:paymentData="payment.data"
								label="Select card"
								@stepLogin="
									(err) => redirectStepLoginWithError(err)
								"
								:validationPayment="validationPayment"
							/>
								<!-- @update:newCard="
									payment.data.bookings.save_card = $event
										? true
										: null
								" -->
						</v-col>
						<v-col cols="12" sm="6">
							<sas-booking-summary
								:property="property"
								:quotes="payment.data.bookings"
							/>

							<v-checkbox
								:rules="[
									(v) => !!v || 'This field is required',
								]"
								v-model="booking.meta.readTerms"
								label="All transactions will incur up to a 3.5% credit card fee*"
								required
							/>

							<div>
								<strong>
									By clicking pay you accept the
									<a
										href="https://breakz.com/privacy-policy/"
										target="_blank"
										class="text-primary"
									>
										Privacy Policy
									</a>
									and
									<a
										href="https://breakz.com/terms-and-conditions/"
										target="_blank"
										class="text-primary"
									>
										Terms and Conditions
									</a>
								</strong>
							</div>

							<v-alert
								v-if="payment.error.message"
								class="mb-3"
								type="error"
							>
								{{ payment.error.message }}
							</v-alert>

							<div
								class="text-red pl-2"
								v-if="
									Object.values(
										payment.data.payment_method ?? {}
									).length === 0 && validationPayment
								"
							>
								Payment field is required
							</div>

							<v-btn
								:loading="payment.loading || loadingStripe"
								block
								color="success"
								size="50"
								type="submit"
							>
								Finish & Pay
							</v-btn>
						</v-col>
					</v-row>

					<v-container
						v-else-if="
							Object.values(returnPaymentIntent.error ?? {})
								?.length > 0 && payment.paymentSuccess
						"
						class="flex-column align-center justify-center"
					>
						<div class="congratulations-container px-5 py-8">
							<v-icon
								class="check-congratulations text-red-darken-3 w-100 mb-5 mx-auto d-block"
								icon="mdi-alpha-x-circle-outline"
							/>

							<h4 class="text-center mb-4 text-capitalize">
								{{ userName }}, your booking has failed!
							</h4>
							<p class="mb-4">
								{{ returnPaymentIntent.error?.message }}
							</p>
							<p class="mb-4">
								Go to your account to try again or contact us
								for help.
							</p>
							<v-row align-h="center" align-v="center">
								<v-btn
									block
									class="action-link mx-5 my-3"
									color="primary"
									size="50"
									@click="redirect"
								>
									Booking page
								</v-btn>
							</v-row>
						</div>
					</v-container>

					<v-container
						v-else-if="
							Object.values(
								returnPaymentIntent.paymentIntent ?? {}
							)?.length > 0 || payment.paymentSuccess
						"
						class="flex-column align-center justify-center"
					>
						<div class="congratulations-container px-5 py-8">
							<v-icon
								class="check-congratulations text-green-darken-3 w-100 mb-5"
								icon="mdi-checkbox-marked-circle"
							/>
							<h4 class="text-center mb-6 text-capitalize">
								Congratulations {{ userName }}
							</h4>
							<v-row
								v-if="isBooking"
								class="flex-column align-center justify-center"
							>
								<p class="mb-4">
									Your booking request for
									<strong class="congratulations-property">{{
										property.properties.name
									}}</strong>
									has been sent.
								</p>
								<p class="mb-4">
									It can take up to 48 hours for your booking
									request to be confirmed. <br />
									An email confirmation will be sent once your
									booking is approved with a link where you
									can finalize booking.
								</p>
								<p class="mb-4">
									View Booking Application progress by going
									into the My Booking sessions in your
									account.
								</p>
							</v-row>
							<v-row
								v-else
								class="flex-column align-center justify-center"
							>
								<p class="mb-4">
									You have successfully booked your stay at
									the
									<strong class="congratulations-property">{{
										property.properties.name
									}}</strong
									>.
									<br />
									This is just the begining of your wonderful
									holiday!
								</p>
								<p class="mb-4">
									Check your inbox for more details about your
									booking including so you can stay in touch.
								</p>
							</v-row>

							<v-row
								v-if="logged && !createAccount"
								class="flex-column align-center justify-center mb-3"
							>
								<p class="mb-4">
									<strong> Enjoy your holiday!</strong>
								</p>
								<v-btn
									block
									class="action-link px-5 py-3"
									color="primary"
									size="50"
									@click="redirect"
								>
									Go to my account
								</v-btn>
							</v-row>
						</div>
					</v-container>
				</template>

				<!-- Step Header -->
				<template #step-header="bind">
					<div
						v-if="
							['resume', 'payment'].includes(bind.id) &&
							!payment.response.success
						"
					>
						<sas-booking-summary
							:property="property"
							:quotes="payment.data.bookings"
						/>
					</div>
				</template>
			</booking-stepper>
		</v-defaults-provider>
	</div>
</template>

<script setup>
const { defineAsyncComponent, ref, reactive, computed, watch, onBeforeMount } =
	Vue;

const BookingStepper = defineAsyncComponent(() =>
	loadModule(SAS_URL + "/src/components/booking/Stepper.vue", options)
);

const sasBookingSummary = defineAsyncComponent(() =>
	loadModule(SAS_URL + "/src/components/booking/Summary.vue", options)
);

const sasBookingRules = defineAsyncComponent(() =>
	loadModule(SAS_URL + "/src/components/booking/Rules.vue", options)
);

const AppLoading = defineAsyncComponent(() =>
	loadModule(SAS_URL + "/src/components/AppLoading.vue", options)
);

const vendorShowLeanFull = defineAsyncComponent(() =>
	loadModule(`${SAS_URL}/src/components/vendor/ShowLeanFull.vue`, options)
);

const GuestLogin = defineAsyncComponent(() =>
	loadModule(`${SAS_URL}/src/components/guests/login/Login.vue`, options)
);

const props = defineProps({
	property: { type: Object, default: () => ({}) },
	search: { type: Object, default: () => ({}) },
	singleProperty: { type: Boolean, default: false },
});
const emit = defineEmits(["step"]);
const loginForm = ref({ error: { message: null } });
const loadingStep = ref(false);
const validationPayment = ref(false);
const store = useUserStore();
const { getUser } = Pinia.storeToRefs(store);
const userName = ref(
	`${useUserStore().getUser?.first_name ?? ""} ${
		useUserStore().getUser?.last_name ?? ""
	}`
);
const stripeData = reactive({ card: { instance: false }, stripe: false });
const returnPaymentIntent = ref({ paymentIntent: {}, error: {} });
const loadingStripe = ref(false);
const guestItems = reactive([
	["adult", "adults", "(18+)"],
	["child", "children", "(3 - 17)"],
	["infant", "infants", "(0 - 2)"],
	["pet", "pets", ""],
]);
const storeStripe = useStripeStore();

onBeforeMount(() => {
	stepper.value.step = !!getUser.value ? "reviewHouseRules&Payment" : "login";

	if (Object.values(props.search ?? {}).length > 0) {
		booking.data.quotes.adults = props.search.adults ?? 1;
		booking.data.quotes.children = props.search.children ?? 0;
		booking.data.quotes.pets = props.search.pets ?? 0;
		booking.data.quotes.guests = props.search.guests ?? 1;
		booking.data.quotes.infants = props.search.infants ?? 0;
		booking.data.quotes.infantAges = props.search.infantAges ?? 0;
		booking.data.quotes.checkin_date =
			props.search.initial_date || props.search.checkin_date;
		booking.data.quotes.checkout_date =
			props.search.final_date || props.search.checkout_date;
	}
	setTimeout(() => (loadingStep.value = true), 1000);

	if (props.singleProperty) {
		booking.submit();
	}

	emit("step", stepper.value.step);
});

const isMobile = computed(() => {
	return window.screen.width <= 959;
});

const property = computed(() => {
	return useProperty(props.property);
});

const isBooking = computed(() => {
	try {
		return !!booking.data.booking_approval;
	} catch {
		return false;
	}
});

const socialLogin = computed(() => {
	const socials = getUser.value?.social_login;
	return socials.apple || socials.google || socials.facebook;
});

const createAccount = computed(() => {
	return (
		getUser.value && getUser.value?.missing_password && !socialLogin.value
	);
});

const logged = async (response) => {
	loginForm.value.error.message = null;
	payment.data.bookings.account_id = response.result.account_id;
	stepper.value.step = !!getUser.value ? "reviewHouseRules&Payment" : "login";
};

const stepper = ref({
	step: !!getUser.value ? "reviewHouseRules&Payment" : "login",
	hideNavigation: false,
	items: [
		{
			id: "login",
			title: "Login",
		},
		{
			id: "reviewHouseRules&Payment",
			title: "Review House Rules & Payment",
			validate() {
				return !!getUser.value;
			},
		},
	],
});

const booking = useAxios({
	method: "post",
	url: "/quotes/store",
	headers: { SearchAndStayApiToken: "null" },
	data: {
		save_card: true,
		account_id: getUser.value?.id,
		booking_approval: 0,
		quotes: {
			property_id: property.value.properties.id,
			checkin_date: "",
			checkout_date: "",
			adults: 1,
			children: 0,
			infants: 0,
			infantAges: [],
			// guests: 0,
			promocode: "",
		},
	},
	response: {
		data: {
			save_card: true,
			account_id: getUser.value?.id,
			booking_approval: 0,
			booking_payments: {
				base_total: 0,
				base_sub_total: 0,
				base_grand_total: 0,
				base_grand_sub_total: 0,
				taxes: [],
			},
		},
	},
	reset() {
		booking.data.quotes.checkin_date = "";
		booking.data.quotes.checkout_date = "";
		booking.data.quotes.adults = 1;
		booking.data.quotes.children = 0;
		booking.data.quotes.infants = 0;
		booking.data.quotes.guests = 0;
		booking.data.quotes.promocode = "";
	},
	onSuccess(response) {
		booking.data.account_id = getUser.value?.id;
		booking.data.booking_approval = response.data.data.booking_approval;
		booking.data.quotes.session_id = response.data.data.session_id;
		payment.data.bookings = response.data.data;
		payment.data.bookings.adults = booking.data.quotes.adults;
		payment.data.bookings.children = booking.data.quotes.children;
		payment.data.bookings.infants = booking.data.quotes.infants;
		payment.data.bookings.pets = booking.data.quotes.pets;
		booking.data.property = response.data.data.property;
		payment.data.bookings.payment_method_code = "cash";
		if (stepper.value.step === "booking") {
			stepper.value.step = !!getUser.value
				? "reviewHouseRules&Payment"
				: "login";
		}
	},
	onError(error) {
		if ([403, 409].includes(error?.status)) {
			stepper.value.step = "login";
		}
	},
	meta: {
		readTerms: false,
	},
});

const paymentBooking = async () => {
	loadingStripe.value = true;
	validationPayment.value = false;
	if (storeStripe.valueRadio === "new-card") {
		await storeStripe.createPaymentMethod();
	}

	if (storeStripe.cardValidation.type === "error") {
		loadingStripe.value = false;
		return;
	}

	if (Object.values(payment.data.payment_method ?? {}).length === 0) {
		validationPayment.value = true;
		loadingStripe.value = false;

		return;
	}
	payment.data.bookings.account_id = getUser.value?.account_id;
	payment.submit();
};

const payment = useAxios({
	method: "post",
	url: "/booking/store",
	paymentSuccess: false,
	response: { success: false },
	data: {
		bookings: { save_card: true },
		payment_method: {},
		financial: {
			customer: {
				name: `${getUser.value?.first_name ?? ""} ${
					getUser.value?.last_name ?? ""
				}`,
				email: getUser.value?.login,
				customer_type: "guest",
				origin: "guest",
				main: 1,
			},
			card_type: {
				type: "subscription",
				main: 1,
			},
		},
	},
	reset() {
		payment.data.bookings = {};
		payment.data.payment_method = {};
	},
	async onSuccess(response) {
		await stripe3DS(response.data.data);

		setTimeout(() => {
			payment.paymentSuccess = true;
			payment.reset();
			booking.reset();
			stepper.value.hideNavigation = true;
			loadingStripe.value = false;
		});
		// stepper.value.step = "success";
	},
	onError(error) {
		payment.paymentSuccess = false;
		if ([403, 409].includes(error?.status)) {
			stepper.value.step = "login";
		}
	},
});

const stripeKey = useAxios({
	url: "/vendor/stripe_keys?",
	method: "get",
	autoSubmit: true,
	onSuccess() {
		stripeData.stripe = Stripe(stripeKey.response.data.key);
	},
});

const stripe3DS = async (booking) => {
	try {
		loadingStripe.value = true;

		const parcelIntent = booking.booking_payments.booking_payment_parcels
			.find((p) => p.status === "pending" && p.payment_intent?.length)
			?.payment_intent.find((p) => p.status === "requires_action");
		if (parcelIntent) {
			const { stripe } = stripeData;
			const elements = stripe.elements();
			stripeData.card.instance = elements.create("card");

			const intentValues =
				parcelIntent.payment_intent_log &&
				parcelIntent.payment_intent_log[0];
			const { paymentIntent, error } = await stripe.confirmCardPayment(
				intentValues.client_secret,
				{ payment_method: intentValues.payment_method }
			);

			returnPaymentIntent.value = { paymentIntent, error };
		}
	} catch (e) {
		console.error(e);
	}
};

const isPropertyWithPets = (property) => {
	const pets_ids = [159];
	if (property?.property_amenities?.find((el) => pets_ids.includes(el.id))) {
		guestItems.push(["pet", "pets", ""]);
		booking.data.guests.pets = 0;
	}
};

watch(property, (value) => {
	isPropertyWithPets(value);
});

const redirectStepLoginWithError = (error) => {
	loginForm.value.error.message = error.message ?? "";
	useUserStore().setLogout();
	stepper.value.step = "login";
};

const redirect = () => {
	window.location.href = `/${window.env.sas_guest_panel_route}`;
};

watch(
	() => stepper.value.step,
	(r) => {
		if (r === "reviewHouseRules&Payment") {
			loadingStep.value = false;

			setTimeout(() => (loadingStep.value = true), 1000);
		}
		emit("step", r);
	},
	{ deep: true }
);
</script>

<style scoped>
p {
	text-align: center;
}

.action-link {
	min-width: 260px;
}

.congratulations-container {
	border: 1px solid #cfcfcf;
}

.congratulations-property {
	font-weight: bolder;
}

.check-congratulations {
	font-size: 60px;
}
</style>
