import type React from "react";
import { memo, useEffect, useRef, useState } from "react";
import { Editor } from "react-draft-wysiwyg";

import { ContentState, convertFromRaw, convertToRaw, EditorState } from "draft-js";
import { stateFromHTML } from "draft-js-import-html";
import draftToHtml from "draftjs-to-html";
import htmlToDraft from "html-to-draftjs";
import { draftToMarkdown, markdownToDraft } from "markdown-draft-js";
import "react-draft-wysiwyg/dist/react-draft-wysiwyg.css";

import { formatIframe } from "./utils";

import * as S from "./style";

const RichText = (props: IRichTextProps): JSX.Element => {
	const {
		value,
		error,
		placeholder,
		onChange,
		disabled,
		editorID,
		handleValidation,
		validators,
		html = false,
		delayed,
	} = props;

	const valueUnformatted = value ? formatIframe(value, true) : "";

	const rawData = html ? htmlToDraft(valueUnformatted) : markdownToDraft(value);
	const { contentBlocks, entityMap } = rawData;
	const contentState = html ? ContentState.createFromBlockArray(contentBlocks, entityMap) : convertFromRaw(rawData);

	const [editorState, setEditorState] = useState(() => EditorState.createWithContent(contentState));
	const timeOutRef = useRef<ReturnType<typeof setTimeout>>();
	const isMountRef = useRef(true);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		const rawData = html ? htmlToDraft(valueUnformatted) : markdownToDraft(value);
		const { contentBlocks, entityMap } = rawData;
		const contentState = html ? ContentState.createFromBlockArray(contentBlocks, entityMap) : convertFromRaw(rawData);
		setEditorState(EditorState.createWithContent(contentState));
	}, [editorID]);

	// biome-ignore lint/correctness/useExhaustiveDependencies: TODO: fix this
	useEffect(() => {
		if (isMountRef.current) {
			isMountRef.current = false;
			return;
		}
		if (delayed !== false) {
			timeOutRef.current && clearTimeout(timeOutRef.current);
			timeOutRef.current = setTimeout(() => {
				delayedChange();
			}, 300);
		}
	}, [editorState]);

	const handleOnChange = (editorState: EditorState) => {
		setEditorState(editorState);
		delayed === false && delayedChange();
	};

	const delayedChange = () => {
		const content = editorState.getCurrentContent();
		const plainContent = content.getPlainText();
		const rawObject = convertToRaw(content);
		const markdownString =
			plainContent === "" ? plainContent : html ? formatIframe(draftToHtml(rawObject)) : draftToMarkdown(rawObject);

		onChange(markdownString);
		error && handleValidation && handleValidation(plainContent);
	};

	const handlePaste = (pastedValue: string) => {
		const content = stateFromHTML(pastedValue);
		setEditorState(() => EditorState.createWithContent(content));
		const rawObject = convertToRaw(content);
		const markdownString = html ? formatIframe(draftToHtml(rawObject)) : draftToMarkdown(rawObject);

		onChange(markdownString);
		return false;
	};

	const handleOnBlur = (_event: React.FocusEvent<HTMLTextAreaElement>, editorState: EditorState) => {
		const plainContent = editorState.getCurrentContent().getPlainText();
		handleValidation?.(plainContent, validators);
	};

	const toolbar = {
		options: ["inline", "list", "link", "blockType"],
		inline: {
			inDropdown: false,
			options: ["bold", "italic"],
			bold: { icon: "/img/icons/bold.svg" },
			italic: { icon: "/img/icons/italic.svg" },
		},
		list: { inDropdown: false, options: ["unordered"], unordered: { icon: "/img/icons/list.svg" } },
		link: {
			inDropdown: false,
			options: ["link"],
			showOpenOptionOnHover: false,
			popupClassName: "richTextLinkModal",
			link: { icon: "/img/icons/link.svg" },
		},
		blockType: { inDropdown: true, options: ["H1", "H2", "H3", "H4", "Normal"], className: "richTextBlockType" },
	};

	const editorLabels = {
		"components.controls.blocktype.h1": "Heading 1",
		"components.controls.blocktype.h2": "Heading 2",
		"components.controls.blocktype.h3": "Heading 3",
		"components.controls.blocktype.h4": "Heading 4",
	};

	return (
		<S.EditorWrapper error={error} disabled={disabled} data-testid="rich-text-wrapper">
			<Editor
				editorState={editorState}
				toolbarClassName="richTextToolbar"
				wrapperClassName="richTextWrapper"
				editorClassName="richTextEditor"
				onEditorStateChange={handleOnChange}
				toolbar={toolbar}
				localization={{ locale: "en", translations: editorLabels }}
				placeholder={placeholder}
				handlePastedText={handlePaste}
				onBlur={handleOnBlur}
			/>
		</S.EditorWrapper>
	);
};

export interface IRichTextProps {
	editorID: number;
	value: string;
	error?: boolean;
	placeholder?: string;
	disabled?: boolean;
	onChange: (value: string) => void;
	handleValidation?: (value: string, validators?: Record<string, unknown>) => void;
	html: boolean;
	delayed?: boolean;
	validators?: Record<string, unknown>;
}

export default memo(RichText);
