import type React from 'react';
import { createContext, useContext, useState } from 'react';

import ConfirmationModal from '../../Components/UI/ConfirmationModal/ConfirmationModal';
import type {
	ConfirmationModalConfig,
	ConfirmationModalInterface
} from '../../Components/UI/ConfirmationModal/ConfirmationModalHelper';
import ToastNotification from '../../Components/UI/ToastNotification/ToastNotification';
import type { ToastNotificationInterface } from '../../Components/UI/ToastNotification/ToastNotificationHelper';

interface UiContextValue {
	// confirmModal: (title: string, message: string) => Promise<boolean | null>;
	confirmModal: (config: ConfirmationModalConfig) => Promise<boolean | FormData | null>;
	toastNotification: (
		severity: 'info' | 'error' | 'warning' | 'success',
		message: string,
		duration?: number
	) => Promise<boolean | null>;
}

const UiContext = createContext<UiContextValue | undefined>(undefined);

export const useUiContext = (): UiContextValue => {
	const context = useContext(UiContext);
	if (!context) {
		console.warn('useUiContext called outside of a UiProvider');
		// Return default no-op functions
		return {
			confirmModal: async () => null,
			toastNotification: async () => null
		};
	}
	return context;
};

export const UiProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
	const [confirmationModalProps, setConfirmationModalProps] =
		useState<ConfirmationModalInterface | null>(null);
	const [toastNotificationProps, setToastNotificationProps] =
		useState<ToastNotificationInterface | null>(null);

	const confirmModal = async (
		config: ConfirmationModalConfig
	): Promise<boolean | FormData | null> =>
		new Promise<boolean | FormData | null>((resolve) => {
			setConfirmationModalProps({
				open: true,
				config,
				handleClose: () => {
					resolve(false);
					setConfirmationModalProps(null);
				},
				handleConfirm: (isThirdButtonClicked?: boolean) => {
					// IMPORTANT:
					// the return value of confirm will be true if no value in the form is populated
					// take this into consideration when passing confirmationModal with forms
					// i.e. if form and true is returned, check if any additional logic should be applied
					// such as treating it as not confirmed because a checkbox was not checked
					// in component handle confirm like below to get the form values:
					// const jsonObject = {};
					// if (isConfirmed !== true) {
					// 	(isConfirmed as FormData).forEach((value, key) => {
					// 		jsonObject[key] = value;
					// 	});
					// }
					const form = document.getElementById('confirmation-modal-form') as HTMLFormElement;
					const formData = new FormData(form);
					if (isThirdButtonClicked) {
						formData.append('thirdButtonTriggered', 'true');
					}
					const fdArr = Array.from(formData.entries());
					resolve(fdArr.length > 0 ? formData : true);
					setConfirmationModalProps(null);
				}
			});
		});

	const toastNotification = async (
		severity: 'info' | 'error' | 'warning' | 'success',
		message: string,
		duration?: number
	): Promise<boolean | null> =>
		new Promise<boolean | null>((resolve) => {
			setToastNotificationProps({
				duration,
				open: true,
				severity,
				handleClose: () => {
					resolve(true);
					setToastNotificationProps(null);
				},
				message
			});
		});

	const ConfirmationModalWrapper = () =>
		confirmationModalProps ? (
			<ConfirmationModal
				open={confirmationModalProps.open}
				handleClose={confirmationModalProps.handleClose}
				handleConfirm={confirmationModalProps.handleConfirm}
				handleThirdButton={confirmationModalProps.handleThirdButton}
				config={confirmationModalProps.config}
			/>
		) : null;

	const ToastNotificationWrapper = () =>
		toastNotificationProps ? (
			<ToastNotification
				open={toastNotificationProps.open}
				handleClose={toastNotificationProps.handleClose}
				message={toastNotificationProps.message}
				severity={toastNotificationProps.severity}
				duration={toastNotificationProps.duration}
			/>
		) : null;

	if (!children) {
		throw new Error('UiProvider must have children');
	}
	// <ConfirmationContext.Provider value={{ confirmModal }}>
	return (
		<UiContext.Provider value={{ confirmModal, toastNotification }}>
			{children}
			<ConfirmationModalWrapper />
			<ToastNotificationWrapper />
		</UiContext.Provider>
	);
	/* </ConfirmationContext.Provider> */
};
