import { __ } from '@wordpress/i18n';
import {
	useCallback,
	useEffect,
	useMemo,
	useRef,
	useState,
} from '@wordpress/element';
import { SelectControl, TextControl } from '@wordpress/components';
import apiFetch from '@wordpress/api-fetch';
import NoDataPlaceholder from '../shared/NoDataPlaceholder';

import FormRow from './components/FormRow';
import FormConfigurationModal from './components/FormConfigurationModal';
import {
	fetchSettings,
	isLianaMailerConfigured,
	sendBatchToggle,
} from './components/utils';
import useNotice from '../shared/useNotice';

type FormsProps = {
	forms: Array< FormDataRow >;
	endpoints: {
		lianaAutomationToggle: string;
		lianaMailerForm: string;
		lianaMailerProxy: string;
		lianaMailerSave: string;
		lianaMailerToggle: string;
	};
	lianaAutomationEnabled: boolean;
	lianaAutomationSettingsUrl: string;
	lianaMailerEnabled: boolean;
	lianaMailerSettingsUrl: string;
};

/**
 * Forms component
 *
 * @param {FormsProps} props - The component props.
 * @return                   - The forms component.
 */
export default function Forms( props: FormsProps ) {
	const {
		endpoints,
		lianaAutomationEnabled,
		lianaAutomationSettingsUrl,
		lianaMailerEnabled,
		lianaMailerSettingsUrl,
	} = props;
	const { showNotice } = useNotice();
	const [ forms, setForms ] = useState( props.forms );
	const [ textFilter, setTextFilter ] = useState( '' );
	const [ typeFilter, setTypeFilter ] = useState( '' );
	const [ modalOpen, setModalOpen ] = useState( false );
	const [ modalFormData, setModalFormData ] = useState( null );
	const [ modalFormSettings, setModalFormSettings ] = useState( null );
	const [ loading, setLoading ] = useState( false );
	const [ errorFields, setErrorFields ] = useState( [] );
	const pendingToggles = useRef( new Map() );
	const toggleTimeout = useRef( null );

	const handleSave = useCallback(
		async ( formStateSettings ) => {
			setLoading( true );
			try {
				const payload = formStateSettings;
				const response = await apiFetch( {
					url: endpoints.lianaMailerSave,
					method: 'POST',
					body: JSON.stringify( payload ),
					headers: {
						'Content-Type': 'application/json',
					},
				} );
				showNotice(
					response.success ? 'success' : 'error',
					response.message
				);
				if ( response.success ) {
					setModalOpen( false );
					setModalFormData( null );
					setModalFormSettings( null );
					setErrorFields( [] );
					setForms( ( prevState ) =>
						prevState.map( ( form ) => {
							if (
								form.id === formStateSettings.form_id &&
								form.plugin.slug === formStateSettings.plugin
							) {
								return {
									...form,
									lianaMailerConfigured:
										isLianaMailerConfigured(
											formStateSettings
										),
									lianaMailerConnected:
										formStateSettings.enabled,
								};
							}
							return form;
						} )
					);
				}
				if ( ! response.success ) {
					setErrorFields( response.missing_fields || [] );
					setModalFormSettings( formStateSettings );
				}
			} catch ( error: any ) {
				showNotice(
					'error',
					error?.message ??
						__( 'Error saving form settings', 'liana-with-growthstack' )
				);
				setErrorFields( error?.missing_fields || [] );
				setModalFormSettings( formStateSettings );
			} finally {
				setLoading( false );
			}
		},
		[ endpoints.lianaMailerSave, showNotice ]
	);

	const openConfiguration = useCallback(
		async ( form: FormDataRow ) => {
			setLoading( true );

			const endpoint = endpoints.lianaMailerForm
				.replace( ':plugin', form.plugin.slug )
				.replace( ':form_id', form.id.toString() );
			const settings = await fetchSettings( endpoint );
			if ( settings ) {
				setModalFormData( form );
				setModalFormSettings( {
					...settings,
					form_id: form.id,
					plugin: form.plugin.slug,
				} );
				setModalOpen( true );
			} else {
				showNotice(
					'error',
					__( 'Error fetching form settings', 'liana-with-growthstack' )
				);
			}
			setLoading( false );
		},
		[ endpoints.lianaMailerForm, showNotice ]
	);

	// Open modal from URL query parameters (e.g., ?gs_configure_form=123&gs_form_plugin=gravityforms)
	useEffect( () => {
		if ( ! lianaMailerEnabled ) {
			return;
		}

		const urlParams = new URLSearchParams( window.location.search );
		const formId = urlParams.get( 'gs_configure_form' );
		const pluginSlug = urlParams.get( 'gs_form_plugin' );

		if ( formId && pluginSlug ) {
			const form = forms.find(
				( f ) =>
					f.id.toString() === formId && f.plugin.slug === pluginSlug
			);

			if ( form ) {
				openConfiguration( form );

				// Clean up URL parameters after opening modal
				urlParams.delete( 'gs_configure_form' );
				urlParams.delete( 'gs_form_plugin' );
				const newUrl = urlParams.toString()
					? `${ window.location.pathname }?${ urlParams.toString() }`
					: window.location.pathname;
				window.history.replaceState( {}, '', newUrl );
			}
		}
	}, [ forms, lianaMailerEnabled, openConfiguration ] );

	const filteredForms = useMemo(
		() =>
			forms
				.filter( ( form ) =>
					typeFilter ? form.plugin.slug === typeFilter : true
				)
				.filter( ( form ) =>
					form.name.toLowerCase().includes( textFilter.toLowerCase() )
				),
		[ forms, typeFilter, textFilter ]
	);

	const formTypeOptions = useMemo( () => {
		const uniquePlugins = Array.from(
			new Map(
				props.forms.map( ( form ) => [ form.plugin.slug, form.plugin ] )
			).values()
		);
		return uniquePlugins.map( ( plugin ) => (
			<option key={ plugin.slug } value={ plugin.slug }>
				{ plugin.name }
			</option>
		) );
	}, [ props.forms ] );

	const toggleAutomationForm = useCallback(
		async (
			{ formPlugin, id }: { formPlugin: string; id: number },
			event: React.ChangeEvent< HTMLInputElement >
		) => {
			const active = event.target.checked;

			pendingToggles.current.set( `${ formPlugin }-${ id }`, {
				formPlugin,
				id,
				active,
			} );

			setForms( ( prevState: Array< FormDataRow > ) =>
				prevState.map( ( form: FormDataRow ) => {
					if ( form.id === id && form.plugin.slug === formPlugin ) {
						return {
							...form,
							lianaAutomationConnected: active,
						};
					}
					return form;
				} )
			);

			if ( toggleTimeout.current ) {
				clearTimeout( toggleTimeout.current );
			}

			// Set new timeout to batch send
			toggleTimeout.current = setTimeout( () => {
				const allForms = Array.from( pendingToggles.current.values() );
				sendBatchToggle( endpoints.lianaAutomationToggle, allForms );
				pendingToggles.current.clear();
			}, 1000 ); // 1000ms delay
		},
		[ endpoints.lianaAutomationToggle ]
	);

	useEffect( () => {
		const sendPendingToggles = () => {
			if ( pendingToggles.current.size > 0 ) {
				const allForms = Array.from( pendingToggles.current.values() );
				sendBatchToggle( endpoints.lianaAutomationToggle, allForms );
				pendingToggles.current.clear();
			}
		};

		const handleVisibilityChange = () => {
			if ( document.hidden ) {
				// Page is being hidden, send pending toggles
				sendPendingToggles();
			}
		};

		const handleBeforeUnload = () => {
			sendPendingToggles();
		};

		// Add event listeners
		document.addEventListener( 'visibilitychange', handleVisibilityChange );
		window.addEventListener( 'beforeunload', handleBeforeUnload );

		// Cleanup
		return () => {
			document.removeEventListener(
				'visibilitychange',
				handleVisibilityChange
			);
			window.removeEventListener( 'beforeunload', handleBeforeUnload );
		};
	}, [ endpoints.lianaAutomationToggle ] );

	/**
	 * Toggles the connection status of a LianaMailer form.
	 * @param param0            - The form details.
	 * @param param0.formPlugin - The form plugin.
	 * @param param0.id         - The form ID.
	 * @param event             - The change event.
	 */
	const toggleMailerForm = useCallback(
		async (
			{ formPlugin, id }: { formPlugin: string; id: number },
			event: React.ChangeEvent< HTMLInputElement >
		) => {
			const checked = event.target.checked;
			const originalForms = [ ...forms ];

			setForms( ( prevState: Array< FormDataRow > ) =>
				prevState.map( ( form: FormDataRow ) => {
					if ( form.id === id && form.plugin.slug === formPlugin ) {
						return {
							...form,
							lianaMailerConnected: checked,
						};
					}
					return form;
				} )
			);

			try {
				const endpoint = endpoints.lianaMailerToggle;

				const response = await apiFetch( {
					url: endpoint,
					method: 'PATCH',
					headers: {
						'Content-Type': 'application/json',
					},
					body: JSON.stringify( {
						action: 'toggleActive',
						formPlugin,
						id,
						active: checked,
					} ),
				} );

				if ( ! response.success ) {
					setForms( originalForms );
				}
			} catch ( error ) {
				setForms( originalForms );
			}
		},
		[ endpoints.lianaMailerToggle, forms ]
	);

	if ( ! forms || forms.length === 0 ) {
		return (
			<>
				<div className="gs-header-box">
					<div className="gs-header-box__main">
						<h2>{ __( 'Forms', 'liana-with-growthstack' ) }</h2>
						<p>
							{ __(
								'View and control the connection status of your forms to LianaAutomation and LianaMailer.',
								'liana-with-growthstack'
							) }
						</p>
					</div>
				</div>
				<div className="gs-forms gs-box">
					<NoDataPlaceholder type="personalization">
						<p>{ __( 'No forms found', 'liana-with-growthstack' ) }</p>
						<p>
							{ __(
								'Please create a form to enable tracking.',
								'liana-with-growthstack'
							) }
						</p>
					</NoDataPlaceholder>
				</div>
			</>
		);
	}

	return (
		<>
			<div className="gs-header-box">
				<div className="gs-header-box__main">
					<h2>{ __( 'Forms', 'liana-with-growthstack' ) }</h2>
					<p>
						{ __(
							'View and control the connection status of your forms to LianaAutomation and LianaMailer.',
							'liana-with-growthstack'
						) }
					</p>
				</div>
			</div>

			<div className="gs-forms gs-box">
				<div className="gs-flex gs-flex--justify-between">
					<div>
						<span className="gs-box__label">
							{ forms.length } { __( 'Forms', 'liana-with-growthstack' ) }
						</span>
						<p className="gs-box__desc">
							{ __(
								'List of forms which are available to be connected.',
								'liana-with-growthstack'
							) }
						</p>
					</div>
					<div className="gs-flex gs-box__actions">
						<TextControl
							onChange={ ( value ) => {
								setTextFilter( value );
							} }
							placeholder="Search"
							value={ textFilter }
						/>
						{ formTypeOptions.length > 1 && (
							<SelectControl
								onChange={ ( value ) => {
									setTypeFilter( value );
								} }
								name="filter"
								id="filter"
							>
								<option value="">
									{ __( 'Filter by plugin', 'liana-with-growthstack' ) }
								</option>
								{ formTypeOptions }
							</SelectControl>
						) }
					</div>
				</div>
				<div className="gs-table__wrapper">
					<table className="gs-table gs-forms__list">
						<thead>
							<tr>
								<th>{ __( 'Name', 'liana-with-growthstack' ) }</th>
								<th>
									{ __(
										'LianaAutomation connected',
										'liana-with-growthstack'
									) }
								</th>
								<th>
									{ __(
										'LianaMailer connected',
										'liana-with-growthstack'
									) }
								</th>
								<th>{ __( 'Form plugin', 'liana-with-growthstack' ) }</th>
							</tr>
						</thead>
						<tbody>
							{ filteredForms.map( ( form: FormDataRow ) => (
								<FormRow
									key={ form.id }
									form={ form }
									openConfiguration={ () =>
										openConfiguration( form )
									}
									lianaAutomationEnabled={
										lianaAutomationEnabled
									}
									lianaMailerEnabled={ lianaMailerEnabled }
									lianaAutomationSettingsUrl={
										lianaAutomationSettingsUrl
									}
									lianaMailerSettingsUrl={
										lianaMailerSettingsUrl
									}
									toggleAutomationForm={
										toggleAutomationForm
									}
									toggleMailerForm={ toggleMailerForm }
								/>
							) ) }
						</tbody>
					</table>
				</div>
			</div>
			{ lianaMailerEnabled && (
				<FormConfigurationModal
					data={ modalFormData }
					errorFields={ errorFields }
					formSettings={ modalFormSettings }
					isOpen={ modalOpen }
					loading={ loading }
					onClose={ () => setModalOpen( false ) }
					onSave={ ( formStateSettings ) => {
						handleSave( formStateSettings );
					} }
					proxyEndpoint={ endpoints.lianaMailerProxy }
				/>
			) }
		</>
	);
}
