import { Form, Formik } from "formik";
import apiFetch from "@wordpress/api-fetch";
import { useEffect, useState } from "@wordpress/element";
import { __ } from "@wordpress/i18n";
import * as Yup from "yup";
import { ConnectedFocusError } from "focus-formik-error";
import {
	detailFields,
	infoFields,
	ingredientsFields,
	instructionFields,
	galleryFields,
	nutritionFields,
	notesFields,
} from "./defaults";
import RecipeDetails from "./RecipeDetails.jsx";
import RecipeInfo from "./RecipeInfo.jsx";
import RecipeIngredients from "./RecipeIngredients.jsx";
import RecipeInstructions from "./RecipeInstructions.jsx";
import RecipeGallery from "./RecipeGallery.jsx";
import RecipeNutrition from "./RecipeNutrition.jsx";
import RecipeNotes from "./RecipeNotes.jsx";
import { ToastContainer, toast } from "react-toastify";

const { globalSettings } = DeliciousRecipesProUD;

const RecipeSubmission = (props) => {
	const { rest_nonce, guest_mode, recipeEditMode, recipeEditId } = props;
	const [editMode, setEditMode] = useState(recipeEditMode ?? false);
	const [editRecipeId, setEditRecipeId] = useState(recipeEditId ?? null);
	const [selectedButton, setSelectedButton] = useState("save");
	const [editPostStatus, setEditPostStatus] = useState("draft");

	const [recaptchaEnabled, setRecaptchaEnabled] = useState([]);
	const [recaptchaVersion, setRecaptchaVersion] = useState('');
	const [googleSiteKey, setGoogleSiteKey] = useState('');
	const [googleSecretKey, setGoogleSecretKey] = useState('');
	const [reCaptchaValidationResult, setReCaptchaValidationResult] = useState('');

	/**
	 * Changing the text of the Submit button.
	 */
	const [updateButtonText, setupdateButtonText] = useState(
		__("Submit Recipe", "delicious-recipes-pro")
	);
	const [saveButtonText, setSaveButtonText] = useState(
		__("Save Recipe", "delicious-recipes-pro")
	);

	const enabledItems = DeliciousRecipesProUD.recipeSubmissionStructure.enabledItems;

	const validationSchema = Yup.object().shape({
		// Recipe Details
		title: enabledItems.recipeTitle[0] && enabledItems.recipeTitle[1]
			? Yup.string().required(__("Recipe title is required", "delicious-recipes-pro"))
			: Yup.string(),
		featuredImage: enabledItems.recipeImage[0] && enabledItems.recipeImage[1]
			? Yup.string().required(__("Recipe image is required", "delicious-recipes-pro"))
			: Yup.string(),
		description: enabledItems.description[0] && enabledItems.description[1]
			? Yup.string().required(__("Description is required", "delicious-recipes-pro"))
			: Yup.string(),
		cookingMethods: enabledItems.cookingMethods[0] && enabledItems.cookingMethods[1]
			? Yup.array().min(1, __("At least one cooking method is required", "delicious-recipes-pro"))
			: Yup.array(),
		cuisines: enabledItems.cuisine[0] && enabledItems.cuisine[1]
			? Yup.array().min(1, __("At least one cuisine is required", "delicious-recipes-pro"))
			: Yup.array(),
		courses: enabledItems.courses[0] && enabledItems.courses[1]
			? Yup.array().min(1, __("At least one course is required", "delicious-recipes-pro"))
			: Yup.array(),
		recipeKeys: enabledItems.recipeKeys[0] && enabledItems.recipeKeys[1]
			? Yup.array().min(1, __("At least one recipe key is required", "delicious-recipes-pro"))
			: Yup.array(),
		recipeBadges: enabledItems.recipeBadge[0] && enabledItems.recipeBadge[1]
			? Yup.array().min(1, __("At least one recipe badge is required", "delicious-recipes-pro"))
			: Yup.array(),
		recipeDietaries: enabledItems.recipeDietary[0] && enabledItems.recipeDietary[1]
			? Yup.array().min(1, __("At least one dietary option is required", "delicious-recipes-pro"))
			: Yup.array(),

		// Recipe Info
		recipeSubtitle: enabledItems.recipeSubtitle[0] && enabledItems.recipeSubtitle[1]
			? Yup.string().required(__("Recipe subtitle is required", "delicious-recipes-pro"))
			: Yup.string(),
		recipeDescription: enabledItems.recipeDescription[0] && enabledItems.recipeDescription[1]
			? Yup.string().required(__("Recipe description is required", "delicious-recipes-pro"))
			: Yup.string(),
		estimatedCost: enabledItems.estimatedCost[0] && enabledItems.estimatedCost[1]
			? Yup.string().required(__("Estimated cost is required", "delicious-recipes-pro"))
			: Yup.string(),
		cookingTemp: enabledItems.cookingTemp[0] && enabledItems.cookingTemp[1]
			? Yup.string().required(__("Cooking temp is required", "delicious-recipes-pro"))
			: Yup.string(),
		bestSeason: enabledItems.bestSeason[0] && enabledItems.bestSeason[1]
			? Yup.string().required(__("Best season is required", "delicious-recipes-pro"))
			: Yup.string(),
		recipeKeywords: enabledItems.recipeKeywords[0] && enabledItems.recipeKeywords[1]
			? Yup.string().required(__("Recipe keywords are required", "delicious-recipes-pro"))
			: Yup.string(),
		prepTime: enabledItems.preparationTime[0] && enabledItems.preparationTime[1]
			? Yup.string().required(__("Prep time is required", "delicious-recipes-pro"))
			: Yup.string(),
		cookTime: enabledItems.cookingTime[0] && enabledItems.cookingTime[1]
			? Yup.string().required(__("Cook time is required", "delicious-recipes-pro"))
			: Yup.string(),
		restTime: enabledItems.restTime[0] && enabledItems.restTime[1]
			? Yup.string().required(__("Rest time is required", "delicious-recipes-pro"))
			: Yup.string(),
		recipeCalories: enabledItems.calories[0] && enabledItems.calories[1]
			? Yup.string().required(__("Calories is required", "delicious-recipes-pro"))
			: Yup.string(),
		difficultyLevel: enabledItems.difficultyLevel[0] && enabledItems.difficultyLevel[1]
			? Yup.string().required(__("Difficulty level is required", "delicious-recipes-pro"))
			: Yup.string(),

		// Recipe Ingredients
		noOfServings: enabledItems.noOfServings[0] && enabledItems.noOfServings[1]
			? Yup.string().required(__("Number of servings is required", "delicious-recipes-pro"))
			: Yup.string(),
		recipeIngredients: enabledItems.ingredientsSection[0] && enabledItems.ingredientsSection[1]
			? Yup.array().min(1, __("At least one ingredient is required", "delicious-recipes-pro"))
			: Yup.array(),

		// Recipe Instructions
		recipeInstructions: enabledItems.instructionSection[0] && enabledItems.instructionSection[1]
			? Yup.array().min(1, __("At least one instruction is required", "delicious-recipes-pro"))
			: Yup.array(),

		// Recipe Gallery
		imageGalleryImages: enabledItems.imageGallery[0] && enabledItems.imageGallery[1]
			? Yup.array().min(1, __("At least one image is required", "delicious-recipes-pro"))
			: Yup.array(),
		videoGalleryVids: enabledItems.videoGallery[0] && enabledItems.videoGallery[1]
			? Yup.array().min(1, __("At least one video is required", "delicious-recipes-pro"))
			: Yup.array(),

		// Recipe Notes
		recipeNotes: enabledItems.notes[0] && enabledItems.notes[1]
			? Yup.string().required(__("Recipe notes are required", "delicious-recipes-pro"))
			: Yup.string(),
		adminNotes: enabledItems.notesToAdmin[0] && enabledItems.notesToAdmin[1]
			? Yup.string().required(__("Recipe notes to admin are required", "delicious-recipes-pro"))
			: Yup.string(),
	});

	const [defaultValues, setdefaultValues] = useState({
		...detailFields,
		...infoFields,
		...ingredientsFields,
		...instructionFields,
		...galleryFields,
		...nutritionFields,
		...notesFields,
	});


	const [initialDefaultValues] = useState(defaultValues);

	useEffect(() => {
		editMode && editRecipeId && getRecipeSettings(editRecipeId);
		editMode &&
			editRecipeId &&
			setupdateButtonText(__("Update Recipe", "delicious-recipes-pro"));
	}, [editRecipeId]);

	const getRecipeSettings = async (editRecipeId) => {
		apiFetch({
			path: "/deliciousrecipe/v1/recipe/usrdb/" + editRecipeId,
			method: "GET",
		})
			.then((response) => {
				let defaultValues = response.data.recipe_metas;
				if (defaultValues) {
					if (defaultValues.courses && defaultValues.courses.length) {
						defaultValues.courses = defaultValues.courses.map(
							(item) => {
								return {
									value: item,
									label: item,
								};
							}
						);
					}
					if (
						defaultValues.cuisines &&
						defaultValues.cuisines.length
					) {
						defaultValues.cuisines = defaultValues.cuisines.map(
							(item) => {
								return {
									value: item,
									label: item,
								};
							}
						);
					}
					if (
						defaultValues.recipeKeys &&
						defaultValues.recipeKeys.length
					) {
						defaultValues.recipeKeys = defaultValues.recipeKeys.map(
							(item) => {
								return {
									value: item,
									label: item,
								};
							}
						);
					}
					if (
						defaultValues.cookingMethods &&
						defaultValues.cookingMethods.length
					) {
						defaultValues.cookingMethods = defaultValues.cookingMethods.map(
							(item) => {
								return {
									value: item,
									label: item,
								};
							}
						);
					}
					if (
						defaultValues.recipeBadges &&
						defaultValues.recipeBadges.length
					) {
						defaultValues.recipeBadges = defaultValues.recipeBadges.map(
							(item) => {
								return {
									value: item,
									label: item,
								};
							}
						);
					}

					if (
						defaultValues.recipeDietaries &&
						defaultValues.recipeDietaries.length
					) {
						defaultValues.recipeDietaries = defaultValues.recipeDietaries.map(
							(item) => {
								return {
									value: item,
									label: item,
								};
							}
						);
					}
				}
				setdefaultValues(defaultValues);
				setEditPostStatus(response?.data?.recipe_status);
			})
			.catch((error) => {
				console.log(error);
			});
	};

	const handleFormSave = async (formdata, isSave = false, resetForm) => {
		// Validate the form data against the schema before saving
		try {
			await validationSchema.validate(formdata, { abortEarly: false });
		} catch (err) {
			// If validation fails, display errors and return without saving
			err.inner.forEach(error => {
				toast.error(error.message);
			});
			return;
		}

		let guestMode = guest_mode ? true : false;
		let formdataCopy = { ...formdata };
		if (formdata) {
			if (formdata.courses && formdata.courses.length) {
				formdataCopy.courses = formdata.courses.map((item) => {
					return item.value;
				});
			}
			if (formdata.cuisines && formdata.cuisines.length) {
				formdataCopy.cuisines = formdata.cuisines.map((item) => {
					return item.value;
				});
			}
			if (formdata.recipeKeys && formdata.recipeKeys.length) {
				formdataCopy.recipeKeys = formdata.recipeKeys.map((item) => {
					return item.value;
				});
			}
			if (formdata.cookingMethods && formdata.cookingMethods.length) {
				formdataCopy.cookingMethods = formdata.cookingMethods.map(
					(item) => {
						return item.value;
					}
				);
			}
			if (formdata.recipeBadges && formdata.recipeBadges.length) {
				formdataCopy.recipeBadges = formdata.recipeBadges.map(
					(item) => {
						return item.value;
					}
				);
			}

			if (formdata.recipeDietaries && formdata.recipeDietaries.length) {
				formdataCopy.recipeDietaries = formdata.recipeDietaries.map(
					(item) => {
						return item.value;
					}
				);
			}
			setdefaultValues(formdata);
		}

		if (editMode && editRecipeId) {
			if (selectedButton === "update") {
				setupdateButtonText(__("Updating...", "delicious-recipes-pro"));
			}
			if (selectedButton === "save") {
				setSaveButtonText(__("Saving...", "delicious-recipes-pro"));
			}

			let submitReview =
				editPostStatus == "draft" && selectedButton === "update"
					? true
					: false;

			apiFetch({
				path: "/deliciousrecipe/v1/recipe/usrdb/" + editRecipeId,
				method: "POST",
				data: {
					nonce: rest_nonce,
					formdata: formdataCopy,
					submitReview: submitReview,
				},
			}).then((response) => {
				if (response.success) {
					toast.success(
						__(
							"Recipe settings updated successfully !!",
							"delicious-recipes-pro"
						)
					);
					if (submitReview) {
						resetForm({ values: initialDefaultValues });
						typeof setEditMode === "function" && setEditMode(false);
						typeof setEditRecipeId === "function" &&
							setEditRecipeId(null);
					}
				}
				setupdateButtonText(
					__("Update Recipe", "delicious-recipes-pro")
				);
				setSaveButtonText(__("Save Recipe", "delicious-recipes-pro"));
			});
		} else {
			selectedButton === "save"
				? setSaveButtonText(__("Saving...", "delicious-recipes-pro"))
				: setupdateButtonText(
					__("Submitting...", "delicious-recipes-pro")
				);
			apiFetch({
				path: "/deliciousrecipe/v1/recipe/usrdb",
				method: "POST",
				data: {
					nonce: rest_nonce,
					guest: guestMode,
					draft: isSave,
					formdata: formdataCopy,
				},
			}).then((response) => {
				if (response.success) {
					if (isSave && response?.recipe_id) {
						typeof setEditMode === "function" && setEditMode(true);
						typeof setEditRecipeId === "function" &&
							setEditRecipeId(response?.recipe_id);
					} else {
						window.location.reload(false);
					}
					{
						!isSave &&
							globalSettings.enablePendingMode[0] &&
							"yes" === globalSettings.enablePendingMode[0]
							? toast.warning(
								__(
									"Recipe settings saved successfully!! It will be published after admin review.",
									"delicious-recipes-pro"
								)
							)
							: toast.success(
								__(
									"Recipe settings saved successfully !! View your recipes at My Recipes.",
									"delicious-recipes-pro"
								)
							);
					}
				}
				setupdateButtonText(
					__("Submit Recipe", "delicious-recipes-pro")
				);
				setSaveButtonText(__("Save Recipe", "delicious-recipes-pro"));
			});
		}
	};

	const handleListChange = (updatedList, arrayKey, values) => {
		let tempList = {
			...values,
			[`${arrayKey}`]: updatedList,
		};
		setdefaultValues(tempList);
	};

	if ('yes' === recaptchaEnabled && googleSiteKey) {
		const script = document.createElement('script');
		if (recaptchaVersion === 'v3') {
			script.src = `https://www.google.com/recaptcha/api.js?render=${googleSiteKey}`;
		} else if (recaptchaVersion === 'v2') {
			script.src = `https://www.google.com/recaptcha/api.js`;
		}
		script.async = true;
		script.defer = true;
		document.body.appendChild(script);
	}

	useEffect(() => {
		getGlobalSettings();
	}, []);

	const getGlobalSettings = () => {
		apiFetch({ path: '/deliciousrecipe/v1/recipe-global' })
			.then((response) => {
				if (response.success && response.data) {
					setRecaptchaEnabled(response.data.recipe_settings.recaptchaEnabledForRecipe[0]);
					setRecaptchaVersion(response.data.recipe_settings.recpatchaVersion);
					setGoogleSiteKey(response.data.recipe_settings.recaptchaSiteKey);
					setGoogleSecretKey(response.data.recipe_settings.recaptchaSecretKey);
				} else {
					console.error("Invalid response:", response);
					throw new Error("Invalid response from the server");
				}
			})
			.catch((error) => {
				console.error("Error fetching data:", error);
			});
	}

	const validateRecaptcha = async () => {
		if (!recaptchaEnabled) {
			return false;
		}
		let recaptchaResponse
		getGlobalSettings();
		if ('v3' === recaptchaVersion) {
			recaptchaResponse = await grecaptcha.ready(() => {
				grecaptcha.execute(googleSiteKey, { action: 'submit' }).then((token) => {
					return token;
				});
			})
		} else {
			recaptchaResponse = grecaptcha.getResponse();
		}

		if (recaptchaResponse.length === 0) {
			toast.error(
				__("Please verify that you are not a robot.", "delicious-recipes-pro")
			);
			return false;
		} else {
			const response = await apiFetch({
				path: '/deliciousrecipe/v1/recipe-recaptcha',
				method: 'POST',
				data: {
					recaptchaResponse: recaptchaResponse,
					googleSecretKey: googleSecretKey
				}
			});

			if (response.success) {
				setReCaptchaValidationResult(response.data);
				if (response.data.success) {
					return true;
				} else {
					toast.error(
						__("reCAPTCHA verification failed. Please try again.", "delicious-recipes-pro")
					);
					return false;
				}
			} else {
				toast.error(
					__("Error validating reCAPTCHA. Please try again.", "delicious-recipes-pro")
				);
				return false;
			}
		}
	}

	return (
		<div className="dr-ud__submit-recipe-wrapper">
			<header className="dr-ud__header">
				{!guest_mode && (
					<h2 className="dr-ud__title">
						{editMode && editRecipeId
							? __("Edit Recipe", "delicious-recipes-pro")
							: __("Submit Recipe", "delicious-recipes-pro")}
					</h2>
				)}
				{"undefined" !=
					typeof globalSettings.recipeSubmissionGuideline &&
					"" !== globalSettings.recipeSubmissionGuideline && (
						<div
							className="dr-ud__desc"
							dangerouslySetInnerHTML={{
								__html:
									globalSettings.recipeSubmissionGuideline,
							}}
						></div>
					)}
			</header>

			<Formik
				enableReinitialize
				validationSchema={validationSchema}
				initialValues={defaultValues}
				onSubmit={async (values, { resetForm, setFieldValue }) => {
					await handleFormSave(values, false, resetForm);
					resetForm();
					setFieldValue(defaultValues);
				}}
			>
				{({
					handleSubmit,
					handleChange,
					setFieldValue,
					values,
					touched,
					errors,
					resetForm,
					handleReset,
					setFieldTouched,
				}) => (
					<Form className="dr-form__fields-wrapper">
						<ConnectedFocusError />
						{globalSettings.recipeFieldsOrder &&
							globalSettings.recipeFieldsOrder.map(
								(fieldGrp, index) => {
									switch (fieldGrp.id) {
										case "recipe-details":
											return (
												"yes" ===
												fieldGrp.enable[0] && (
													<RecipeDetails
														key={index}
														setFieldValue={
															setFieldValue
														}
														setFieldTouched={
															setFieldTouched
														}
														values={values}
														errors={errors}
														touched={touched}
														sectionTitle={
															fieldGrp.sectionTitle
														}
													/>
												)
											);

										case "recipe-info":
											return (
												"yes" ===
												fieldGrp.enable[0] && (
													<RecipeInfo
														key={index}
														values={values}
														setFieldValue={
															setFieldValue
														}
														sectionTitle={
															fieldGrp.sectionTitle
														}
														errors={errors}
														touched={touched}
													/>
												)
											);

										case "recipe-ingredients":
											return (
												"yes" ===
												fieldGrp.enable[0] && (
													<RecipeIngredients
														key={index}
														values={values}
														handleListChange={
															handleListChange
														}
														sectionTitle={
															fieldGrp.sectionTitle
														}
														errors={errors}
														touched={touched}
													/>
												)
											);

										case "recipe-instructions":
											return (
												"yes" ===
												fieldGrp.enable[0] && (
													<RecipeInstructions
														key={index}
														values={values}
														handleListChange={
															handleListChange
														}
														setFieldValue={
															setFieldValue
														}
														sectionTitle={
															fieldGrp.sectionTitle
														}
														errors={errors}
														touched={touched}
													/>
												)
											);

										case "recipe-gallery":
											return (
												"yes" ===
												fieldGrp.enable[0] && (
													<RecipeGallery
														key={index}
														values={values}
														setFieldValue={
															setFieldValue
														}
														sectionTitle={
															fieldGrp.sectionTitle
														}
														errors={errors}
														touched={touched}
													/>
												)
											);

										case "recipe-nutrition":
										case "recipe-others":
											return (
												"yes" ===
												fieldGrp.enable[0] && (
													<RecipeNutrition
														key={index}
														values={values}
														sectionTitle={
															fieldGrp.sectionTitle
														}
														errors={errors}
														touched={touched}
													/>
												)
											);

										case "recipe-notes":
											return (
												"yes" ===
												fieldGrp.enable[0] && (
													<RecipeNotes
														key={index}
														values={values}
														setFieldValue={
															setFieldValue
														}
														sectionTitle={
															fieldGrp.sectionTitle
														}
														errors={errors}
														touched={touched}
													/>
												)
											);
									}
								}
							)}

						{"undefined" !=
							typeof globalSettings.recipeDisclaimer &&
							"" !== globalSettings.recipeDisclaimer && (
								<div
									className="dr-ud__desc"
									dangerouslySetInnerHTML={{
										__html: globalSettings.recipeDisclaimer,
									}}
								></div>
							)}

						<div className="dr-form__section sticky-section">
							{recaptchaEnabled == 'yes' && recaptchaVersion == 'v2' && (
								<div>
									<div className="dr-form__field g-recaptcha" data-sitekey={googleSiteKey}></div>
								</div>
							)}
							<div className="dr-button-group">
								{editPostStatus === "draft" && (
									<button
										type="button"
										className="dr-btn btn-secondary"
										onClick={async (event) => {
											if (touched.title && values.title) {
												setSelectedButton("save");
												if (recaptchaEnabled) {
													const isValid = await validateRecaptcha();
													if (isValid === true) {
														handleFormSave(
															values,
															true,
															handleReset
														);
													} else {
														event.preventDefault();
													}
												} else {
													handleFormSave(
														values,
														true,
														handleReset
													);
												}
											} else {
												handleSubmit();
											}
										}}
									>
										{saveButtonText}
									</button>
								)}
								<input
									type="submit"
									value={updateButtonText}
									className="dr-btn btn-primary"
									onClick={async (event) => {
										if (recaptchaEnabled) {
											const isValid = await validateRecaptcha();
											if (isValid) {
												setSelectedButton("update")
											} else {
												event.preventDefault();
											}
										} else {
											setSelectedButton("update")
										}
									}}
								/>
							</div>
						</div>
					</Form>
				)}
			</Formik>
			<ToastContainer
				position="bottom-right"
				autoClose={5000}
				hideProgressBar
				newestOnTop
				closeOnClick
				pauseOnFocusLoss
			/>
		</div>
	);
};

export default RecipeSubmission;
