import { useEffect, useRef } from "react";
import FroalaEditorComponent from "react-froala-wysiwyg";
import { connect } from "react-redux";

import { galleryActions } from "@ax/containers/Gallery";
import { decodeEntities } from "@ax/helpers";
import type { IImage, IRootState, ISite } from "@ax/types";

import FroalaEditor from "froala-editor";

import { buttons, buttonsFull, inlineToolbar, wysiwygConfig } from "./config";
import "./vendors";

import * as S from "./style";

const Wysiwyg = (props: IWysiwygProps) => {
	const {
		value,
		error,
		onChange,
		placeholder,
		full = true,
		disabled,
		handleValidation,
		site,
		token,
		uploadImage,
		inline = false,
	} = props;

	const imageSite = site ? site.id : "global";
	const editorRef = useRef<any>(null);
	const errorRef = useRef(error);
	errorRef.current = error;

	useEffect(() => {
		if (!editorRef.current) return;
		disabled ? editorRef.current.edit.off() : editorRef.current.edit.on();
	}, [disabled]);

	const handleChange = (model: string) => {
		onChange(model);
		const stripedHtml = decodeEntities(model);
		setTimeout(() => {
			errorRef.current && handleValidation?.(stripedHtml);
		}, 300);
	};

	const dynamicConfig = {
		placeholderText: placeholder,
		toolbarButtons: inline ? inlineToolbar() : full ? buttonsFull() : buttons(),
		toolbarInline: inline,
		charCounterCount: !inline,
		imageUpload: false,
		multiLine: !inline,
		enter: inline ? FroalaEditor.ENTER_BR : FroalaEditor.ENTER_P,
		requestHeaders: {
			Authorization: `bearer ${token}`,
		},
		events: {
			initialized(this: any) {
				editorRef.current = this;

				if (disabled) {
					this.edit.off();
				}

				if (full && !inline) {
					const editorEl = this.$el?.get?.(0) || this.el;
					if (editorEl) {
						const getPopupPosition = () => {
							const editorRect = editorEl.getBoundingClientRect?.();
							return {
								x: editorRect ? editorRect.left + editorRect.width / 2 - 100 : window.innerWidth / 2 - 100,
								y: editorRect ? editorRect.top + 50 : 50,
							};
						};

						const showPopup = (name: string, template: any, keepVisible = false) => {
							this.popups.create(name, template);
							if (!keepVisible) {
								this.popups.onHide(name, () => false);
							}
							const pos = getPopupPosition();
							this.popups.show(name, pos.x, pos.y, 50);
						};

						const showErrorPopup = () => {
							const errorPopupTemplate = {
								custom_layer:
									'<div style="padding: 15px 30px; text-align: center; color: #d32f2f;">Upload failed</div>',
							};
							showPopup("image.uploadError", errorPopupTemplate);
							setTimeout(() => this.popups.hide("image.uploadError"), 3000);
						};

						editorEl.addEventListener("drop", async (e: DragEvent) => {
							e.preventDefault();
							const files = e.dataTransfer?.files;
							if (files && files.length > 0) {
								const imageFile = files[0];
								if (imageFile.type.startsWith("image/")) {
									let isUploading = true;
									const uploadingTemplate = {
										custom_layer:
											'<div style="padding: 15px 30px; text-align: center; white-space: nowrap;">Image uploading...</div>',
									};
									this.popups.create("image.uploading", uploadingTemplate);
									this.popups.onHide("image.uploading", () => {
										if (isUploading) {
											setTimeout(() => {
												if (isUploading) {
													const pos = getPopupPosition();
													this.popups.show("image.uploading", pos.x, pos.y, 50);
												}
											}, 0);
										}
									});
									const pos = getPopupPosition();
									this.popups.show("image.uploading", pos.x, pos.y, 50);

									try {
										const result = await uploadImage(imageFile, imageSite);
										isUploading = false;
										this.popups.hide("image.uploading");
										if (result) {
											this.image.insert(result.url, true, null, this.image.get(), null);
										} else {
											showErrorPopup();
										}
									} catch (error) {
										isUploading = false;
										this.popups.hide("image.uploading");
										showErrorPopup();
										console.error("Upload failed:", error);
									}
								}
							}
						});
					}
				}
			},
			blur: function (this: any) {
				const html = this.html.get();
				const stripedHtml = decodeEntities(html);
				handleValidation?.(stripedHtml);
			},
		},
	};

	const config = { ...wysiwygConfig(), ...dynamicConfig };

	return (
		<S.EditorWrapper error={error} disabled={disabled} data-testid="wysiwyg-wrapper">
			<FroalaEditorComponent tag="textarea" model={value} config={config} onModelChange={handleChange} />
		</S.EditorWrapper>
	);
};

interface IProps {
	value: string;
	full?: boolean;
	error?: boolean;
	placeholder?: string;
	token: string;
	onChange: (value: string) => void;
	disabled?: boolean;
	handleValidation?: (value: string) => void;
	site: ISite;
	inline?: boolean;
}

const mapStateToProps = (state: IRootState) => ({
	token: state.app.token,
});

interface IDispatchProps {
	uploadImage: (imageFile: File, site: number | string) => Promise<IImage | null>;
}

const mapDispatchToProps = {
	uploadImage: galleryActions.uploadImage,
};

export type IWysiwygProps = IProps & IDispatchProps;

export default connect(mapStateToProps, mapDispatchToProps)(Wysiwyg);
