<template>
	<div
		class="bg-grey-lighten-3 text-center pa-3 rounded-lg text-h6 mb-6"
		v-if="!!userStore.getUser"
	>
		You're logged as
		{{
			`${userStore.getUser.first_name ?? ""} ${
				userStore.getUser.last_name ?? ""
			}`
		}}.
		<v-btn variant="text" @click="logout">Logout</v-btn>
	</div>

	<v-defaults-provider
		:defaults="{ global: { disabled: !!userStore.getUser } }"
	>
		<v-row>
			<v-col tag="form" class="border-right" cols="12" md="6">
				<h3 class="text-center mb-4">Login</h3>

				<v-row tag="form">
					<v-col class="pt-0" cols="12">
						<v-alert
							v-if="
								messageAlert.show &&
								messageAlert.type === 'login'
							"
							:color="messageAlert.messageType"
							:model-value="messageAlert.show"
							class="w-100 my-3"
							closable
							@click:close="messageAlert.show = false"
						>
							<span v-html="messageAlert.message"></span>
						</v-alert>

						<v-text-field
							v-model.trim="formLogin.email"
							:error="
								$vLogin.formLogin.email.$dirty &&
								$vLogin.formLogin.email.$error
							"
							:error-messages="getErrors($vLogin.formLogin.email)"
							hide-details="auto"
							label="Email"
							placeholder="Email*"
							required
							type="email"
							@blur="$vLogin.formLogin.email.$touch()"
						/>
					</v-col>
					<v-col class="pt-0" cols="12">
						<v-text-field
							v-model.trim="formLogin.password"
							:append-inner-icon="
								showPasswordLogin ? 'mdi-eye' : 'mdi-eye-off'
							"
							:error="
								$vLogin.formLogin.password.$dirty &&
								$vLogin.formLogin.password.$error
							"
							:error-messages="
								getErrors($vLogin.formLogin.password)
							"
							:type="!showPasswordLogin ? 'password' : 'text'"
							hide-details="auto"
							label="Password"
							placeholder="Password*"
							required
							@blur="$vLogin.formLogin.password.$touch()"
							@click:append-inner="
								showPasswordLogin = !showPasswordLogin
							"
						/>
					</v-col>

					<v-col class="pt-0 my-5" cols="12" v-if="isMobile">
						<v-btn
							:loading="loadingLogin"
							variant="outlined"
							block
							color="primary"
							height="50"
							@click="onSubmitLogin(formLogin)"
						>
							Log in
						</v-btn>
					</v-col>
				</v-row>
			</v-col>

			<v-col tag="form" cols="12" md="6">
				<h3 class="text-center mb-4">Sign Up</h3>

				<v-row tag="form">
					<v-col class="pt-0" cols="12" md="6">
						<v-alert
							v-if="
								messageAlert.show &&
								messageAlert.type === 'sign-up'
							"
							:color="messageAlert.messageType"
							:model-value="messageAlert.show"
							class="w-100 my-3"
							closable
							@click:close="messageAlert.show = false"
						>
							<span v-html="messageAlert.message"></span>
						</v-alert>

						<v-text-field
							v-model.trim="formSignUp.first_name"
							:error="
								$vSignUp.formSignUp.first_name.$dirty &&
								$vSignUp.formSignUp.first_name.$error
							"
							:error-messages="
								getErrors($vSignUp.formSignUp.first_name)
							"
							:hint="
								validationLength(
									30,
									formSignUp.first_name.length,
								)
							"
							hide-details="auto"
							label="First Name"
							maxlength="30"
							placeholder="First Name *"
							required
							type="text"
							variant="outlined"
							@blur="$vSignUp.formSignUp.first_name.$touch()"
						/>
					</v-col>
					<v-col class="pt-0" cols="12" md="6">
						<v-text-field
							v-model.trim="formSignUp.last_name"
							:error="
								$vSignUp.formSignUp.last_name.$dirty &&
								$vSignUp.formSignUp.last_name.$error
							"
							:error-messages="
								getErrors($vSignUp.formSignUp.last_name)
							"
							:hint="
								validationLength(
									70,
									formSignUp.last_name.length,
								)
							"
							hide-details="auto"
							label="Last Name"
							maxlength="70"
							placeholder="Last Name*"
							required
							type="text"
							variant="outlined"
							@blur="$vSignUp.formSignUp.last_name.$touch()"
						/>
					</v-col>
					<v-col class="pt-0" cols="12">
						<v-text-field
							v-model.trim="formSignUp.login"
							:error="
								$vSignUp.formSignUp.login.$dirty &&
								$vSignUp.formSignUp.login.$error
							"
							:error-messages="
								getErrors($vSignUp.formSignUp.login)
							"
							hide-details="auto"
							label="Email"
							placeholder="Email*"
							required
							type="email"
							variant="outlined"
							@blur="$vSignUp.formSignUp.login.$touch()"
						/>
					</v-col>
					<v-col class="pt-0" cols="12" md="6">
						<v-text-field
							v-model.trim="formSignUp.password"
							:append-inner-icon="
								showPasswordSignUp ? 'mdi-eye' : 'mdi-eye-off'
							"
							:error="
								$vSignUp.formSignUp.password.$dirty &&
								$vSignUp.formSignUp.password.$error
							"
							:error-messages="
								getErrors($vSignUp.formSignUp.password)
							"
							:hint="
								validationLength(30, formSignUp.password.length)
							"
							:type="!showPasswordSignUp ? 'password' : 'text'"
							hide-details="auto"
							label="Password"
							maxlength="30"
							placeholder="Password*"
							required
							variant="outlined"
							@blur="$vSignUp.formSignUp.password.$touch()"
							@click:append-inner="
								showPasswordSignUp = !showPasswordSignUp
							"
						/>
					</v-col>
					<v-col class="pt-0" cols="12" md="6">
						<v-text-field
							v-model.trim="formSignUp.password_confirmation"
							:append-inner-icon="
								showPasswordConfirmSignUp
									? 'mdi-eye'
									: 'mdi-eye-off'
							"
							:error="
								$vSignUp.formSignUp.password_confirmation
									.$dirty &&
								$vSignUp.formSignUp.password_confirmation.$error
							"
							:error-messages="
								getErrors(
									$vSignUp.formSignUp.password_confirmation,
								)
							"
							:type="
								!showPasswordConfirmSignUp ? 'password' : 'text'
							"
							hide-details="auto"
							label="Confirm Password"
							placeholder="Confirm Password*"
							required
							variant="outlined"
							@blur="
								$vSignUp.formSignUp.password_confirmation.$touch()
							"
							@click:append-inner="
								showPasswordConfirmSignUp =
									!showPasswordConfirmSignUp
							"
						/>
					</v-col>

					<v-col class="pt-0 my-5" cols="12" v-if="isMobile">
						<v-btn
							:loading="loadingSignUp"
							variant="outlined"
							block
							color="primary"
							height="50"
							@click="onSubmitSignUp(formSignUp)"
						>
							Submit
						</v-btn>
					</v-col>
				</v-row>
			</v-col>

			<v-col cols="12" v-if="!isMobile">
				<v-row>
					<v-col cols="12" class="border-right pt-7" md="6">
						<v-btn
							:loading="loadingLogin"
							variant="outlined"
							block
							color="primary"
							height="50"
							@click="onSubmitLogin(formLogin)"
						>
							Log in
						</v-btn>
					</v-col>
					<v-col cols="12" class="pt-7" md="6">
						<v-btn
							:loading="loadingSignUp"
							variant="outlined"
							block
							color="primary"
							height="50"
							@click="onSubmitSignUp(formSignUp)"
						>
							Submit
						</v-btn>
					</v-col>
				</v-row>
			</v-col>

			<v-col
				cols="12"
				v-if="!!userStore.getUser"
				class="mt-7 d-flex justify-end"
			>
				<v-col cols="6">
					<v-btn
						variant="outlined"
						block
						:disabled="false"
						color="primary"
						height="50"
						@click="emit('nextStep')"
					>
						Next
					</v-btn>
				</v-col>
			</v-col>
		</v-row>
	</v-defaults-provider>

	<v-dialog v-model="dialogTwoFactor" width="900">
		<v-card class="pa-4">
			<v-alert
				v-if="messageAlert.show && messageAlert.type === 'two-factor'"
				:color="messageAlert.messageType"
				:model-value="messageAlert.show"
				class="w-100"
				closable
				@click:close="messageAlert.dismissedAlert"
			>
				<span v-html="messageAlert.message"></span>
			</v-alert>

			<SasTwoStepForm
				v-model="formTwoStep"
				:loading="loadingTwoFactor"
				@submit="twoFactorSubmit"
			/>
		</v-card>
	</v-dialog>
</template>

<script setup>
const { useVuelidate } = Vuelidate;
const { email, maxLength, minLength, required, sameAs } = VuelidateValidators;

const SasTwoStepForm = Vue.defineAsyncComponent(() =>
	loadModule(SAS_URL + "/src/components/login/TwoStepForm.vue", options),
);

const emit = defineEmits(["logged", "nextStep"]);
const formLogin = Vue.ref({ email: "", password: "" });
const formTwoStep = Vue.ref({ token: "" });
const formSignUp = Vue.ref({
	first_name: "",
	last_name: "",
	login: "",
	password: "",
	password_confirmation: "",
});
const showPasswordLogin = Vue.ref(false);
const showPasswordSignUp = Vue.ref(false);
const showPasswordConfirmSignUp = Vue.ref(false);
const loadingSignUp = Vue.ref(false);
const loadingLogin = Vue.ref(false);
const loadingTwoFactor = Vue.ref(false);
const dialogTwoFactor = Vue.ref(false);
const userStore = window.useUserStore();
const rulesLogin = {
	formLogin: {
		email: {
			required,
			email,
		},
		password: {
			required,
		},
	},
};
const rulesSignUp = {
	formSignUp: {
		first_name: {
			required,
			maxLength: maxLength(30),
		},
		last_name: {
			required,
			maxLength: maxLength(70),
		},
		login: {
			required,
			email,
		},
		password: {
			required,
			minLength: minLength(5),
			maxLength: maxLength(30),
		},
		password_confirmation: {
			required,
			sameAs: sameAs(Vue.computed(() => formSignUp.value.password)),
		},
	},
};
const $vLogin = useVuelidate(rulesLogin, { formLogin });
const $vSignUp = useVuelidate(rulesSignUp, { formSignUp: formSignUp.value });
const messageAlert = Vue.ref({
	show: false,
	message: "",
	messageType: "error",
	type: "",
});

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

const getErrors = ($v) => {
	if ($v.$dirty && $v.$errors?.length)
		return $v.$errors.map((e) => {
			switch (e.$validator) {
				case "sameAs":
					return "Passwords do not match";
				default:
					return e.$message;
			}
		});
	else return [];
};

const validationLength = (num, value) => String(Number(num - value));

const onSubmitLogin = async (form) => {
	$vLogin.value.formLogin.$touch();
	if ($vLogin.value.formLogin.$invalid) return;

	loadingLogin.value = true;
	await userStore
		.setLoginUser(form)
		.then(async (response) => {
			if (!response.data.success && !response.data.data.two_factor) {
				messageAlert.value.show = true;
				messageAlert.value.message =
					response?.data?.message?.length &&
					Array.isArray(response.data.message)
						? response.data.message[0]
						: response?.data?.message ||
							response?.data?.data ||
							"An error occurred";
				messageAlert.value.messageType = "error";
				messageAlert.value.type = "login";

				return false;
			}

			if (response.data.data.two_factor) {
				dialogTwoFactor.value = true;
				messageAlert.value.show = true;
				messageAlert.value.message =
					"An email was sent with your MFA code. Please, enter the MFA code to complete sign-in.";
				messageAlert.value.messageType = "warning";
				messageAlert.value.type = "two-factor";
			} else {
				await userStore.setSyncUser();
				emit("logged", response.data.data);
			}
		})
		.catch((error) => {
			messageAlert.value.show = true;
			messageAlert.value.message =
				error.response?.data?.message?.length > 0
					? error.response.data.message
					: error.response?.data?.data ?? "An error occurred";

			messageAlert.value.messageType = "error";
			messageAlert.value.type = "login";
		})
		.finally(() => {
			loadingLogin.value = false;
		});
};

const onSubmitSignUp = async (form) => {
	$vSignUp.value.formSignUp.$touch();
	if ($vSignUp.value.formSignUp.$invalid) return;

	loadingSignUp.value = true;
	const token = await window.$recaptcha("login");

	const formUpdated = { "g-recaptcha-response": token, guests: form };
	await userStore
		.setSignUpUser(formUpdated)
		.then(async (r) => {
			if (r.data.message.includes("User already registered")) {
				messageAlert.value.show = true;
				messageAlert.value.message = r.data.message;
				messageAlert.value.messageType = "error";
				messageAlert.value.type = "sign-up";
				return;
			}
			await userStore.setSyncUser();
			emit("logged", r.data.data);
			messageAlert.value.show = false;
			messageAlert.value.message = "";
		})
		.catch((error) => {
			console.error(error, "error");
			messageAlert.value.show = true;
			messageAlert.value.message =
				error.response?.data?.message?.length > 0
					? error.response.data.message
					: error.response?.data?.data ?? "An error occurred";

			messageAlert.value.messageType = "error";
			messageAlert.value.type = "sign-up";
		})
		.finally(() => {
			loadingSignUp.value = false;
		});
};

const twoFactorSubmit = async () => {
	loadingTwoFactor.value = true;
	await userStore
		.setTwoFactor(formTwoStep.value)
		.then(async (response) => {
			if (!response.data.success) {
				messageAlert.value.show = true;
				messageAlert.value.message =
					response.data.message.length &&
					Array.isArray(response.data.message)
						? response.data.message
						: response.data.message ||
							response.data.data ||
							"An error occurred";
				messageAlert.value.messageType = "error";
				messageAlert.value.type = "two-factor";
			} else {
				await userStore.setSyncUser();
				emit("logged", response.data.data);
				dialogTwoFactor.value = false;
			}
		})
		.catch((error) => {
			messageAlert.value.showAlert = true;
			messageAlert.value.message =
				(error.response?.data?.message?.length &&
					error.response?.data?.message) ||
				error.response?.data?.data ||
				"An error occurred";
			messageAlert.value.messageType = "error";
			messageAlert.value.type = "two-factor";
		})
		.finally(() => {
			loadingTwoFactor.value = false;
		});
};

const logout = () => {
	userStore.setLogout();
};
</script>

<style scoped>
.border-right {
	border-right: 2px solid #cacaca;

	@media screen and (max-width: 550px) {
		border: none;

		&:first-child {
			border-bottom: 2px solid #cacaca;
		}
	}
}
</style>
