import React from "react";
import { AddCardPropsInterface } from "./interfaces/AddCardPropsInterface";
import { AddCardStateInterface } from "./interfaces/AddCardStateInterface";
import { MessagesService } from "../MessagesService";
import { SimplyinPaymentMethod } from "../simplyinPayments";

declare global {
	interface Window {
		CCIframe?: any;
		SimplyinActivateNewOrderButton?: () => void;
	}
}

export class AddCard extends React.Component<
	AddCardPropsInterface,
	AddCardStateInterface
> {
	private ccInstance: any = null;
	private containerRef: React.RefObject<HTMLDivElement> = React.createRef();
	private hasTriedToLoad: boolean = false;

	constructor(props: AddCardPropsInterface) {
		super(props);

		this.state = {
			isLoading: false,
			isFormReady: false,
			cardName: "",
			tokenData: null,
			cardSaveChecked: false,
			error: "",
			successMessage: "",
		};
	}

	componentDidMount() {
		this.setupMessageListener();
		this.setupFormSubmitHandler();
		this.checkAndLoadIframe();
	}

	componentDidUpdate(prevProps: AddCardPropsInterface) {
		this.checkAndLoadIframe();

		if (
			!prevProps.paymentChannel.state.isSelected &&
			this.props.paymentChannel.state.isSelected &&
			this.state.isFormReady
		) {
			this.enablePaymentButton();
		}
	}

	private checkAndLoadIframe = () => {
		if (
			this.props.paymentChannel.state.isSelected &&
			!this.hasTriedToLoad &&
			!this.state.isFormReady
		) {
			this.hasTriedToLoad = true;
			this.loadCCIframeScript();
		}
	};

	componentWillUnmount() {
		window.removeEventListener("message", this.handleMessage);
		document.removeEventListener("click", this.handlePlaceOrderClick);
	}

	render() {
		const wasManuallyExpanded = (
			this.props.paymentChannel.constructor as any
		).globalAddCardWasManuallyExpanded;

		return (
			<div
				ref={this.containerRef}
				className="simplyin-add-card-iframe-container"
				style={{
					display:
						wasManuallyExpanded ||
						this.props.paymentChannel.state.isSelected
							? "block"
							: "none",
				}}
			>
				<div className="simplyin-iframe-wrapper">
					<form
						id={`simplyin-add-card-${this.props.itemId}`}
						className="simplyin-add-card-iframe"
						style={{ width: "100%" }}
					>
						{this.state.isLoading && (
							<div
								className="simplyin-iframe-loading"
								id={`simplyin-iframe-loading-${this.props.itemId}`}
								style={{ display: "block" }}
							>
								<p>
									{MessagesService.getMessage(
										"loading_iframe",
										"Loading form...",
									)}
								</p>
							</div>
						)}

						<div
							style={{
								display: this.state.isLoading
									? "none"
									: "block",
							}}
						>
							{(window as any).SimplyIn?.is_login &&
								this.props.enableSaveCard && (
									<div className="form-group card-name-group card-name-group-hidden">
										<label htmlFor="card-name">
											{MessagesService.getMessage(
												"card_name",
												"Card name",
											)}
										</label>
										<input
											type="text"
											id="card-name"
											value={this.state.cardName}
											onChange={this.handleCardNameChange}
											placeholder={MessagesService.getMessage(
												"card_name_placeholder",
												"My card",
											)}
											className="form-control"
										/>
									</div>
								)}

							<div className="form-group">
								<label id="card-number-label">
									{MessagesService.getMessage(
										"card_number",
										"Card number",
									)}
								</label>
								<div
									id="card-number"
									className="card-field"
								></div>
							</div>

							<div className="form-row">
								<div className="form-group">
									<label id="expiry-date-label">
										{MessagesService.getMessage(
											"expiry_date",
											"Expiry date",
										)}
									</label>
									<div
										id="expiry-date"
										className="card-field"
									></div>
								</div>
								<div className="form-group">
									<label id="security-code-label">
										{MessagesService.getMessage(
											"code_cvv_cvc",
											"Code CVV/CVC",
										)}
									</label>
									<div
										id="verification-code"
										className="card-field"
									></div>
								</div>
							</div>

							{this.state.error && (
								<div
									id={`form-error-${this.props.itemId}`}
									className="field-error"
									role="alert"
									style={{ display: "block" }}
								>
									{this.state.error}
								</div>
							)}

							{(window as any).SimplyIn?.is_login &&
								this.props.enableSaveCard && (
									<div className="form-group">
										<label>
											<input
												type="checkbox"
												checked={
													this.state.cardSaveChecked
												}
												onChange={
													this.handleCardSaveChange
												}
											/>
											{MessagesService.getMessage(
												"save_card",
												"Save card for future payments",
											)}
										</label>
									</div>
								)}
						</div>
					</form>
				</div>
			</div>
		);
	}

	private loadCCIframeScript = (): void => {
		if (window.CCIframe) {
			this.initializeCCIframeForm();
			return;
		}

		this.setState({ isLoading: true });

		const script = document.createElement("script");
		script.src = this.props.iframeUrl;
		script.onload = () => {
			this.setState({ isLoading: false });
			this.initializeCCIframeForm();
		};
		script.onerror = () => {
			this.setState({
				isLoading: false,
				error: MessagesService.getMessage(
					"loading_error",
					"Iframe loading error",
				),
			});
		};
		document.head.appendChild(script);
	};

	private initializeCCIframeForm = (): void => {
		const cardNumber = document.querySelector("#card-number");
		const expiryDate = document.querySelector("#expiry-date");
		const verificationCode = document.querySelector("#verification-code");

		if (!cardNumber || !expiryDate || !verificationCode) {
			setTimeout(() => this.initializeCCIframeForm(), 100);
			return;
		}

		try {
			this.ccInstance = window.CCIframe({
				integratorId: this.props.integratorId,
			});

			const options = {
				fonts: [
					{
						family: "Inter",
						src: "url(https://fonts.gstatic.com/s/inter/v18/UcCo3FwrK3iLTcviYwYZ8UA3.woff2) format('woff2')",
						style: "normal",
						weight: "100 900",
					},
				],
				styles: {
					base: {
						color: "rgba(0, 0, 0, 0.8)",
						fontFamily: "Inter",
						fontSize: "14px",
					},
				},
			};

			this.ccInstance.createComponent(
				"cardNumber",
				"#card-number",
				options,
			);
			this.ccInstance.createComponent("cardExp", "#expiry-date", options);
			this.ccInstance.createComponent(
				"cardCvv",
				"#verification-code",
				options,
			);

			this.setState({ isFormReady: true });

			this.enablePaymentButton();
		} catch (error) {
			console.error("Failed to initialize CCIframe:", error);
			this.setState({
				error: MessagesService.getMessage(
					"iframe_error",
					"Iframe loading error",
				),
			});
		}
	};

	private handlePlaceOrderClick = (event: Event): void => {
		const target = event.target as HTMLElement;

		if (
			target.classList &&
			target.closest(".wc-block-components-checkout-place-order-button")
		) {
			if (!this.isAddCardSelected()) {
				return;
			}

			if ((target as any).dataset?.force === "true") {
				return;
			}

			if (this.state.tokenData && this.state.tokenData.oneTimeToken) {
				(target as any).dataset.force = "true";
				target.click();
				return;
			}

			event.preventDefault();
			this.setState({ error: "", successMessage: "" });

			this.createToken();
		}
	};

	private createToken = (): void => {
		if (!this.ccInstance || !this.state.isFormReady) {
			this.setState({
				error: MessagesService.getMessage(
					"iframe_error",
					"Iframe not ready, please wait...",
				),
			});
			this.enablePaymentButton();
			return;
		}

		this.disablePaymentButton();

		this.ccInstance
			.createToken()
			.then((result: any) => {
				if (result && result.oneTimeToken) {
					const tokenData = {
						last4digits: result.last4digits || "",
						oneTimeToken: result.oneTimeToken,
						organization: result.organization || "",
						first6digits: result.first6digits || "",
						cardName: this.state.cardName,
						saveCard: this.state.cardSaveChecked,
					};

					SimplyinPaymentMethod.setCardTokenData(tokenData);

					this.setHiddenFormFields(tokenData);

					window.postMessage(
						{
							type: "SIMPLYIN_CARD_TOKEN",
							itemId: this.props.itemId,
							tokenData: tokenData,
						},
						window.location.origin,
					);

					this.setState({
						tokenData,
						successMessage: MessagesService.getMessage(
							"card_data_valid",
							"Card data is valid. You can place the order.",
						),
					});

					this.props.onCardTokenChange(tokenData);

					if ((window as any).SimplyinActivateNewOrderButton) {
						(window as any).SimplyinActivateNewOrderButton();
					}

					const placeOrderButton = document.querySelector(
						".wc-block-components-checkout-place-order-button",
					) as HTMLButtonElement;

					if (placeOrderButton) {
						(placeOrderButton as any).dataset.force = "true";

						const waitForCheckoutUpdate = () => {
							const observer = new MutationObserver(
								(mutations) => {
									mutations.forEach((mutation) => {
										if (
											mutation.type === "childList" ||
											mutation.type === "attributes"
										) {
											observer.disconnect();
											setTimeout(() => {
												placeOrderButton.click();
											}, 100);
										}
									});
								},
							);

							observer.observe(
								document.querySelector(".wc-block-checkout") ||
									document.body,
								{
									childList: true,
									subtree: true,
									attributes: true,
									attributeFilter: [
										"class",
										"data-block-name",
									],
								},
							);

							setTimeout(() => {
								observer.disconnect();
								placeOrderButton.click();
							}, 2000);
						};

						waitForCheckoutUpdate();
					}
				} else {
					console.error("Invalid token result:", result);
					SimplyinPaymentMethod.setCardTokenData(null);
					this.setState({
						error: MessagesService.getMessage(
							"card_processing_error",
							"Card data processing error. Check entered data.",
						),
					});
					this.enablePaymentButton();
				}
			})
			.catch((error: any) => {
				console.error("CCIframe token creation failed:", error);

				let errorMessage = MessagesService.getMessage(
					"card_processing_error_retry",
					"Card data processing error. Try again.",
				);

				if (error && error.message) {
					if (error.message.includes("400")) {
						errorMessage = MessagesService.getMessage(
							"invalid_card_data",
							"Invalid card data. Check entered information.",
						);
					} else if (error.message.includes("network")) {
						errorMessage = MessagesService.getMessage(
							"connection_problem",
							"Connection problem. Check internet and try again.",
						);
					}
				}

				this.setState({ error: errorMessage });
				this.enablePaymentButton();
			});
	};

	private setHiddenFormFields = (tokenData: any): void => {
		const inputOrganization = document.querySelector(
			'input[name="simplyin_organization"]',
		) as HTMLInputElement;
		if (inputOrganization) {
			inputOrganization.value = tokenData.organization;
		}

		const inputLastDigits = document.querySelector(
			'input[name="simplyin_last_digits"]',
		) as HTMLInputElement;
		if (inputLastDigits) {
			inputLastDigits.value = tokenData.last4digits;
		}

		const inputFirstDigits = document.querySelector(
			'input[name="simplyin_first_digits"]',
		) as HTMLInputElement;
		if (inputFirstDigits) {
			inputFirstDigits.value = tokenData.first6digits;
		}

		const inputOtt = document.querySelector(
			'input[name="simplyin_ott"]',
		) as HTMLInputElement;
		if (inputOtt) {
			inputOtt.value = tokenData.oneTimeToken;
		}

		const inputCardName = document.querySelector(
			'input[name="simplyin_card_name"]',
		) as HTMLInputElement;
		if (inputCardName) {
			const cardNameElement = document.getElementById(
				"card-name",
			) as HTMLInputElement;
			inputCardName.value = cardNameElement ? cardNameElement.value : "";
		}
	};

	private handleCardNameChange = (
		event: React.ChangeEvent<HTMLInputElement>,
	): void => {
		this.setState({ cardName: event.target.value });
	};

	private handleCardSaveChange = (
		event: React.ChangeEvent<HTMLInputElement>,
	): void => {
		this.setState({ cardSaveChecked: event.target.checked });

		if (this.state.cardSaveChecked) {
			this.hideCardNameGroup();
		} else {
			this.showCardNameGroup();
		}
	};

	private showCardNameGroup = (): void => {
		const cardNameGroup = document.querySelector(".card-name-group");
		if (cardNameGroup) {
			cardNameGroup.classList.remove("card-name-group-hidden");
		}
	};

	private hideCardNameGroup = (): void => {
		const cardNameGroup = document.querySelector(".card-name-group");
		if (cardNameGroup) {
			cardNameGroup.classList.add("card-name-group-hidden");
		}
	};

	private isAddCardSelected = (): boolean => {
		return this.props.paymentChannel.state.isSelected;
	};

	private enablePaymentButton = (): void => {
		const placeOrderButton = document.querySelector(
			".wc-block-components-checkout-place-order-button",
		) as HTMLButtonElement;
		if (placeOrderButton) {
			placeOrderButton.disabled = false;
		}
	};

	private disablePaymentButton = (): void => {
		const placeOrderButton = document.querySelector(
			".wc-block-components-checkout-place-order-button",
		) as HTMLButtonElement;
		if (placeOrderButton) {
			placeOrderButton.disabled = true;
		}
	};

	public getTokenData = (): any => {
		return this.state.tokenData;
	};

	public isValid = (): boolean => {
		return this.state.tokenData !== null;
	};

	private checkAndEnableButton = (): void => {
		let isPhoneValid = window.SimplyIn?.validatePhoneNumber?.() || false;
		const phoneCheckbox = document.querySelector(
			"#simply-save-checkbox",
		) as HTMLInputElement;

		if (!phoneCheckbox || !phoneCheckbox.checked) {
			isPhoneValid = true;
		}

		const isAddCardSelected = this.isAddCardSelected();
		const isTokenValid = this.state.tokenData !== null;

		if (isAddCardSelected && isTokenValid && isPhoneValid) {
			this.enablePaymentButton();
		} else {
			this.disablePaymentButton();
		}
	};

	public validate = (): boolean => {
		if (!this.state.tokenData) {
			this.disablePaymentButton();
			return false;
		}

		this.checkAndEnableButton();
		return true;
	};

	private setupMessageListener = (): void => {
		window.addEventListener("message", this.handleMessage);
	};

	private handleMessage = (event: MessageEvent): void => {
		let iframeOrigin: string;
		try {
			iframeOrigin = new URL(this.props.iframeUrl).origin;
		} catch {
			return;
		}
		const allowedOrigins = [window.location.origin, iframeOrigin];
		if (!allowedOrigins.includes(event.origin)) {
			return;
		}

		if (event.data && event.data.property === "fetchToken") {
			const tokenData = event.data.value;
			this.setHiddenFormFields(tokenData);
			SimplyinPaymentMethod.setCardTokenData(tokenData);

			if ((window as any).SimplyinActivateNewOrderButton) {
				(window as any).SimplyinActivateNewOrderButton();
			}
		}

		if (
			event.data &&
			event.data.postmate === "emit" &&
			event.data.value.name === "change"
		) {
			const addCardRadio = document.querySelector(
				"li.simplyin-podaj_karte_patnicza > label",
			) as HTMLInputElement;
			if (addCardRadio) {
				addCardRadio.click();
			}

			if (window.SimplyIn?.validatePhoneNumber?.() === true) {
				console.log("activate new order button");
				window.SimplyinActivateNewOrderButton?.();
			}
		}
	};

	private setupFormSubmitHandler = (): void => {
		document.addEventListener("click", this.handlePlaceOrderClick);
	};
}
