import React from "react";
import { Renderer } from "../renderer";
import { SimplyinPaymentMethod } from "../simplyinPayments";
import { Collapse } from "react-collapse";
import { PaymentOptionlItemPropsInterface } from "./interfaces/PaymentOptionlItemPropsInterface";
import { PaymentOptionItemStateInterface } from "./interfaces/PaymentOptionItemStateInterface";
import { BlikField } from "./BlikField";
import { AddCard } from "./AddCard";
import { StringHelper } from "../StringHelper";

export class PaymentOptionItem extends React.Component<
	PaymentOptionlItemPropsInterface,
	PaymentOptionItemStateInterface
> {
	protected readonly hasParent: boolean = false;
	protected static instances: PaymentOptionItem[] = [];
	protected simplyinOptionId: string;
	protected isBlik: boolean = false;
	protected isAddCard: boolean = false;
	protected isCard: boolean = false;
	protected blikCode: string = "";
	protected cardTokenData: any = null;
	private blikRef: React.RefObject<BlikField> = React.createRef();
	private addCardRef: React.RefObject<AddCard> = React.createRef();

	private wasAddCardManuallyExpanded: boolean = false;
	private static globalAddCardWasManuallyExpanded: boolean = false;
	private isProcessingToggle: boolean = false;

	constructor(props: PaymentOptionlItemPropsInterface) {
		super(props);
		this.state = {
			isOpen: false,
			isSelected: false,
		};
		this.hasParent = props.hasParent ? props.hasParent : false;
		PaymentOptionItem.instances.push(this);
	}

	componentDidMount() {
		if (this.isAddCard) {
			setTimeout(() => {
				this.autoSelectAddCardOption();
			}, 100);

			setTimeout(() => {
				this.checkAllInstancesLoaded();
			}, 200);

			this.setupLoginStateListener();
		}
	}

	private setupLoginStateListener = () => {
		let attempts = 0;
		const maxAttempts = 10;
		let lastLoginState = !!(window as any).SimplyIn?.is_login;

		const checkLoginState = () => {
			attempts++;
			const currentLoginState = !!(window as any).SimplyIn?.is_login;

			if (currentLoginState !== lastLoginState) {
				lastLoginState = currentLoginState;

				setTimeout(() => {
					this.applyGlobalAutoSelectLogic();
				}, 100);

				return;
			}

			if (attempts < maxAttempts) {
				setTimeout(checkLoginState, 500);
			}
		};

		setTimeout(checkLoginState, 500);
	};

	private getClickHandler = () => {
		if (this.isAddCard || this.isCard) {
			return this.handleToggleSelected;
		}

		if (this.isBlik) {
			return this.handleBlikRadioClick;
		}

		if (!this.hasParent) {
			const hasChildren =
				Array.isArray(this.props.items) && this.props.items.length > 0;
			return !hasChildren
				? this.closeAllInstances
				: this.handleToggleSelected;
		}

		return this.handleToggleSelected;
	};

	private handleBlikRadioClick = () => {
		this.handleToggleSelected();

		setTimeout(() => {
			if (this.isBlik && this.blikRef.current) {
				const isValid = this.blikRef.current.validate();
				if (isValid && this.blikRef.current.isValid()) {
					this.enablePaymentButton();
				} else {
					this.disablePaymentButton();
				}
			}
		}, 50);
	};

	render() {
		const { simplyinOptionId, id, value, name, label, icon, items, data } =
			this.props;

		this.simplyinOptionId = simplyinOptionId;

		const hasChildren = Array.isArray(items) && items.length > 0;

		const isBlik =
			typeof data === "object" && "blik" in data && data.blik === true;
		this.isBlik = isBlik ?? false;

		const isAddCard =
			data &&
			typeof data === "object" &&
			"isAddCard" in data &&
			data.isAddCard === true;
		this.isAddCard = isAddCard ?? false;

		const isCard =
			data &&
			typeof data === "object" &&
			"isCard" in data &&
			data.isCard === true;
		this.isCard = isCard ?? false;

		if (isCard && !(window as any).SimplyIn?.is_login) {
			return null;
		}

		return (
			<li
				className={`simplyin-${StringHelper.distillHtmlClassByString(
					label,
				)} simplyin-block-payment-item ${
					hasChildren && "simplyin-has-children"
				} ${isBlik && "simplyin-blik"} ${
					isAddCard && "simplyin-add-card"
				} ${isCard && "simplyin-saved-card"}`}
			>
				<label
					className={`${
						this.state.isSelected ? "simplyin-active" : ""
					} ${isCard ? "simplyin-saved-card" : ""}`}
					htmlFor={id}
				>
					<div className="simplyin-item-top">
						<input
							onClick={this.getClickHandler()}
							id={id}
							value={value}
							type="radio"
							name={name}
						/>
						{isAddCard && (
							<span className="simplyin-plus-icon">
								<svg
									width="18"
									height="18"
									viewBox="0 0 18 18"
									fill="none"
								>
									<path
										d="M9 4.5V13.5"
										stroke="currentColor"
										strokeWidth="2"
										strokeLinecap="round"
									/>
									<path
										d="M4.5 9H13.5"
										stroke="currentColor"
										strokeWidth="2"
										strokeLinecap="round"
									/>
								</svg>
							</span>
						)}
						{!isAddCard && <img src={icon} alt={name} />}
						<span className={"simplyin-block-payment-label"}>
							{label}
						</span>
					</div>
					<div className={"simplyin-block-payment-item-wrapper"}>
						{isBlik && (
							<BlikField
								ref={this.blikRef}
								placeholder={"******"}
								paymentChannel={this}
								onBlikCodeChange={this.handleBlikCodeChange}
								onFocus={this.handleToggleSelected}
							/>
						)}
						{isAddCard && data && (data as any).addCard && (
							<AddCard
								ref={this.addCardRef}
								paymentChannel={this}
								integratorId={
									(data as any).addCard.integratorId
								}
								iframeUrl={(data as any).addCard.iframeUrl}
								enableSaveCard={
									(data as any).addCard.enableSaveCard
								}
								itemId={String(simplyinOptionId)}
								onCardTokenChange={this.handleCardTokenChange}
								onFocus={this.handleToggleSelected}
							/>
						)}
					</div>
				</label>

				<Collapse isOpened={this.state.isOpen}>
					{hasChildren ? (
						<Renderer items={items} hasParent={true} />
					) : null}
				</Collapse>
			</li>
		);
	}

	handleBlikCodeChange = (newBlikCode: string): void => {
		this.blikCode = newBlikCode;
	};

	private checkAndEnableButton = (): void => {
		const simplyInRadio = document.querySelector(
			'input[name="radio-control-wc-payment-method-options"][value="simplyin"]',
		) as HTMLInputElement;
		const isSimplyInSelected = simplyInRadio && simplyInRadio.checked;

		if (!isSimplyInSelected || !this.state.isSelected) {
			return;
		}

		SimplyinPaymentMethod.checkButtonState();
	};

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

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

	handleCardTokenChange = (newCardTokenData: any): void => {
		this.cardTokenData = newCardTokenData;
		this.checkAndEnableButton();
	};

	handleToggleSelected = () => {
		if (this.isProcessingToggle) {
			return;
		}

		if (this.state.isSelected) {
			return;
		}

		this.isProcessingToggle = true;

		try {
			this.closeAllInstances();
			this.setState({
				isOpen: true,
				isSelected: true,
			});

			if (this.isAddCard) {
				this.wasAddCardManuallyExpanded = true;
				PaymentOptionItem.globalAddCardWasManuallyExpanded = true;
			}

			SimplyinPaymentMethod.setPaymentChannelId(this.simplyinOptionId);
			SimplyinPaymentMethod.setIsAddCard(this.isAddCard);
			SimplyinPaymentMethod.setIsCard(this.isCard);
			SimplyinPaymentMethod.setCardTokenData(this.cardTokenData);
			SimplyinPaymentMethod.setIsBlik(this.isBlik);

			const simplyInRadio = document.querySelector(
				'input[name="radio-control-wc-payment-method-options"][value="simplyin"]',
			) as HTMLInputElement;
			const isSimplyInSelected = simplyInRadio && simplyInRadio.checked;

			if (!isSimplyInSelected) {
				return;
			}

			if (this.isBlik && this.blikRef.current) {
				this.checkAndEnableButton();
			} else if (this.isAddCard && this.addCardRef.current) {
				this.enablePaymentButton();
			} else {
				this.checkAndEnableButton();
			}
		} finally {
			setTimeout(() => {
				this.isProcessingToggle = false;
			}, 100);
		}
	};

	closeAllInstances = () => {
		PaymentOptionItem.instances.forEach((instance) => {
			if (instance.isProcessingToggle) {
				return;
			}

			if (
				instance.isAddCard &&
				PaymentOptionItem.globalAddCardWasManuallyExpanded
			) {
				instance.setState({
					isOpen: instance.state.isOpen,
					isSelected: false,
				});
			} else {
				instance.setState({
					isOpen: false,
					isSelected: false,
				});
			}
		});

		if (!this.isBlik && !this.isAddCard) {
			this.enablePaymentButton();
		}
	};

	unselectAllInstances() {
		PaymentOptionItem.instances.forEach((instance) => {
			if (
				instance.isAddCard &&
				PaymentOptionItem.globalAddCardWasManuallyExpanded
			) {
				instance.setState({
					isOpen: instance.state.isOpen,
					isSelected: false,
				});
			} else {
				instance.setState({
					isOpen: instance.state.isOpen,
					isSelected: false,
				});
			}
		});
	}

	public validateBlik(): boolean {
		if (this.isBlik && this.blikRef.current) {
			return this.blikRef.current.validate();
		}
		return true;
	}

	public validateAddCard(): boolean {
		if (this.isAddCard && this.addCardRef.current) {
			return this.addCardRef.current.validate();
		}
		return true;
	}

	public getBlikCode(): string {
		if (this.isBlik && this.blikRef.current) {
			return this.blikRef.current.getBlikCode();
		}
		return "";
	}

	public getCardTokenData(): any {
		if (this.isAddCard && this.addCardRef.current) {
			return this.addCardRef.current.getTokenData();
		}
		return null;
	}

	private checkAllInstancesLoaded = () => {
		const allAddCardInstances = PaymentOptionItem.instances.filter(
			(instance) => instance.isAddCard,
		);
		const addCardCount = allAddCardInstances.length;

		if (
			addCardCount === 1 ||
			this === allAddCardInstances[addCardCount - 1]
		) {
			setTimeout(() => {
				this.applyGlobalAutoSelectLogic();
			}, 50);
		}
	};

	private applyGlobalAutoSelectLogic = () => {
		const savedCardElements = document.querySelectorAll(
			".simplyin-saved-card",
		);
		const hasSavedCards = savedCardElements.length > 0;
		const isLoggedIn = !!(window as any).SimplyIn?.is_login;

		if (!isLoggedIn && hasSavedCards) {
			savedCardElements.forEach((element) => {
				const listItem = element.closest("li");
				if (listItem) {
					(listItem as HTMLElement).style.display = "none";
				}
			});
		}

		const visibleSavedCards = document.querySelectorAll(
			".simplyin-saved-card",
		).length;
		const hasVisibleSavedCards = visibleSavedCards > 0;

		if (isLoggedIn && hasVisibleSavedCards) {
			PaymentOptionItem.globalAddCardWasManuallyExpanded = false;

			PaymentOptionItem.instances.forEach((instance) => {
				if (instance.isAddCard) {
					instance.wasAddCardManuallyExpanded = false;
					instance.setState({
						isOpen: instance.state.isOpen,
						isSelected: false,
					});
				}
			});

			setTimeout(() => {
				SimplyinPaymentMethod.checkButtonState();
			}, 100);

			return;
		}

		if (PaymentOptionItem.globalAddCardWasManuallyExpanded) {
			return;
		}

		const addCardInstances = PaymentOptionItem.instances.filter(
			(instance) => instance.isAddCard,
		);

		if (addCardInstances.length > 0) {
			PaymentOptionItem.instances.forEach((instance) => {
				if (!instance.isAddCard) {
					instance.setState({
						isOpen: instance.state.isOpen,
						isSelected: false,
					});
				}
			});

			const firstAddCard = addCardInstances[0];
			firstAddCard.setState({
				isOpen: firstAddCard.state.isOpen,
				isSelected: true,
			});

			if (!isLoggedIn) {
				firstAddCard.wasAddCardManuallyExpanded = true;
				PaymentOptionItem.globalAddCardWasManuallyExpanded = true;
			}

			SimplyinPaymentMethod.setPaymentChannelId(
				firstAddCard.simplyinOptionId,
			);
			SimplyinPaymentMethod.setIsAddCard(true);
			SimplyinPaymentMethod.setCardTokenData(null);
		}
	};

	private autoSelectAddCardOption = () => {
		const hasSavedCards =
			document.querySelectorAll(".simplyin-saved-card").length > 0;

		if ((window as any).SimplyIn?.is_login && hasSavedCards) {
			if (this.state.isSelected) {
				this.setState({
					isOpen: this.state.isOpen,
					isSelected: false,
				});
			}
			return;
		}

		if (this.isAddCard && !this.state.isSelected) {
			this.unselectAllInstances();

			this.setState({
				isOpen: this.state.isOpen,
				isSelected: true,
			});

			SimplyinPaymentMethod.setPaymentChannelId(this.simplyinOptionId);
			SimplyinPaymentMethod.setIsAddCard(this.isAddCard);
			SimplyinPaymentMethod.setCardTokenData(this.cardTokenData);
		}
	};
}
