/* eslint-disable prettier/prettier */
import { __ } from '@wordpress/i18n';
import { useCallback, useEffect, useMemo, useState } from '@wordpress/element';
import { Button, CheckboxControl, Icon, Modal, SelectControl, Spinner, Tooltip } from '@wordpress/components';

import { getPropertyOptions, getSiteOptions, fetchLianaMailerData, normalizeSiteData } from './utils';
import LianaMailerListSelect from './LianaMailerListSelect';
import Message from '../../shared/Message';
import Toggle from '../../shared/Toggle';
import useNotice from '../../shared/useNotice';

type FormConfigurationModalProps = {
	data: {
		fields: Array< { id: number | string; label: string; type: string, list_choices_field?: boolean, has_subfields?: boolean, parent_id?: number | string } >;
		name: string;
		url: string;
	};
	errorFields: Array< string >;
	formSettings: {
		additional_settings?: string;
		consent?: string;
		enabled: boolean;
		form_id: number | string;
		list: Array< string >;
		list_choices_field?: string;
		opt_in_field?: string;
		plugin: string;
		properties: { [ key: string ]: string };
		site: string;
		split_name_fields?: boolean;
	};
	isOpen: boolean;
	loading: boolean;
	onClose: () => void;
	onSave: ( formStateSettings: any ) => void;
	proxyEndpoint: string;
};

type CheckboxField = {
	label: string;
	value: string;
};

export default function FormConfigurationModal(
	props: FormConfigurationModalProps
) {
	const {
		data,
		errorFields,
		formSettings,
		isOpen,
		loading,
		onClose,
		onSave,
		proxyEndpoint,
	} = props;
	const { showNotice } = useNotice();
	const [ formStateSettings, setFormStateSettings ] = useState( {} );
	const [ lianaMailerData, setLianaMailerData ] = useState( {} );
	const [ lianaMailerConsents, setLianaMailerConsents ] = useState( {} );
	const [ cf7Tooltip, setCf7Tooltip ] = useState( __( 'Copy tag', 'liana-with-growthstack' ) );

	useEffect( () => {
		fetchLianaMailerData( proxyEndpoint, 'sites' )
			.then( ( result ) => {
				const sites = normalizeSiteData( result.data || [] );
				setLianaMailerData( sites );
			} )
			.catch( () => {
				showNotice(
					'error',
					__( 'Error fetching LianaMailer sites and lists.', 'liana-with-growthstack' ),
				);
			} );
	}, [ proxyEndpoint, showNotice ] );

	useEffect( () => {
		setFormStateSettings( formSettings );
	}, [ formSettings ] );

	// Check if no email mapping exists, then auto-populate the first email type input.
	const possiblyPopulateEmail = useCallback(
		() => {
			if ( ! formStateSettings || ! formStateSettings.site || ! formStateSettings.enabled ) {
				return;
			}
			const emailMapped = Object.values( formStateSettings.properties || {} ).includes( 'email' );
			if ( emailMapped ) {
				return;
			}
			const emailField = data?.fields.find( ( field ) => field.type.includes( 'email' ) );
			if ( emailField ) {
				setFormStateSettings( ( prevState ) => ( {
					...prevState,
					properties: {
						...prevState.properties,
						[ emailField.id ]: 'email',
					},
				} ) );
			}
		},
		// Purposefully omitting formStateSettings from dependencies for users to be able to change email mapping after auto-population.
		// eslint-disable-next-line react-hooks/exhaustive-deps
		[ data?.fields, formStateSettings?.site, formStateSettings?.enabled ]
	);

	useEffect( () => {
		possiblyPopulateEmail();
	}, [ possiblyPopulateEmail ] );


	const hasChanges =
		JSON.stringify( formStateSettings ) !== JSON.stringify( formSettings );

	const title =
		__( 'Configure LianaMailer connection for: ', 'liana-with-growthstack' ) +
		data?.name;

	const onListChange = useCallback( ( value: string | number ) => {
		setFormStateSettings( ( prevState ) => ( {
			...prevState,
			lists: value,
		} ) );
		possiblyPopulateEmail();
	}, [ possiblyPopulateEmail ] );

	const onPropertyChange = useCallback( ( fieldId: string, value: string ) => {
		setFormStateSettings( ( prevState ) => ( {
			...prevState,
			properties: {
				...prevState.properties,
				[ fieldId ]: value,
			},
		} ) );
	}, [] );

	const siteOptions = useMemo(
		() => getSiteOptions( lianaMailerData ),
		[ lianaMailerData ]
	);

	const propertyOptions = useMemo(
		() => getPropertyOptions( { formStateSettings, lianaMailerData } ),
		[ formStateSettings, lianaMailerData ]
	);

	const cf7ListsTag = useMemo( () => {
		let tag = '[checkbox lianamailer-join use_label_element';
		const siteData = lianaMailerData[ formStateSettings?.site ];
		const selectedLists = formStateSettings?.lists || [];
		if ( siteData && siteData.lists && siteData.lists.length ) {
			selectedLists.forEach( ( listId: string ) => {
				const list = siteData.lists.find( ( l: any ) => l.id.toString() === listId );
				if ( list ) {
					tag += ` "${ list.name }|${ list.id }"`;
				}
			} );
		}
		tag += ']';
		return tag;
	}, [ lianaMailerData, formStateSettings ] );

	const copyTag = useCallback( () => {
		navigator.clipboard.writeText( cf7ListsTag ).then( () => {
			setCf7Tooltip( __( 'Copied!', 'liana-with-growthstack' ) );
			setTimeout( () => {
				setCf7Tooltip( __( 'Copy tag', 'liana-with-growthstack' ) );
			}, 2000 );
		} );
	}, [ cf7ListsTag ] );

	const optInField = useMemo( () => {
		if ( ! formStateSettings || formStateSettings?.plugin !== 'contactform7' || ! data?.fields.length ) {
			return null;
		}
		const checkboxFields = data.fields.filter( ( field ) => field.type.includes( 'checkbox' ) );
		const optInOptions = checkboxFields.map(
			( field ) => ( {
				label: field.label,
				value: field.id,
			} as CheckboxField )
		);
		const selectHelp = __( 'Select a checkbox field here if the user needs to check it to subscribe to LianaMailer.', 'liana-with-growthstack' );
		if ( formStateSettings?.consent ) {
			optInOptions.unshift( {
				label: __( 'Append opt-in checkbox to the form dynamically', 'liana-with-growthstack' ),
				value: '',
			} );
		} else {
			optInOptions.unshift( {
				label: __( 'None', 'liana-with-growthstack' ),
				value: '',
			} );
		}

		const dynamicOptInRequired = formStateSettings?.consent && ! formStateSettings.opt_in_field ? (
			<CheckboxControl
				help={ __( 'User must check the opt-in field to submit the form.', 'liana-with-growthstack' ) }
				label={ __( 'Opt-in field is required', 'liana-with-growthstack' ) }
				checked={ !!formStateSettings?.opt_in_field_required }
				onChange={ ( checked ) => {
					setFormStateSettings( ( prevState ) => ( {
						...prevState,
						opt_in_field_required: checked ? true : false,
					} ) );
				} }
				value="required"
			/>
			) : null;

		return (
			<>
				<SelectControl
					className="gs-select-control"
					disabled={ ! formStateSettings?.enabled || ! formStateSettings?.site }
					help={ selectHelp }
					label={ __( 'Opt-in Field', 'liana-with-growthstack' ) }
					options={ optInOptions }
					onChange={ ( value ) => {
						setFormStateSettings( ( prevState ) => {
								return {
									...prevState,
									opt_in_field: value,
								};
							} );
						}
					}
					value={ formStateSettings?.opt_in_field || '' }
				/>
				{ dynamicOptInRequired }
			</>
		);
	}, [ formStateSettings, data?.fields ] );

	const lianaConsentField = useMemo( () => {
		if (
			! formStateSettings
			|| formStateSettings?.plugin !== 'contactform7'
			|| ! data?.fields.length
		) {
			return null;
		}

		const site = formStateSettings?.site;
		if ( ! site ) {
			return null;
		}

		const consentTypes = lianaMailerConsents[ site ];
		if ( ! consentTypes || ! consentTypes.length ) {
			return null;
		}

		const consentOptions = consentTypes.map( ( consent: any ) => {
			return {
				label: consent.label,
				value: consent.value,
			};
		} );
		consentOptions.unshift( {
			label: __( 'Choose', 'liana-with-growthstack' ),
			value: '',
		} );

		return (
			<SelectControl
				className="gs-select-control"
				disabled={ ! formStateSettings?.enabled || ! formStateSettings?.site }
				help={ __( 'Optional. You can select LianaMailer consent which is agreed upon when user checks the opt-in field.', 'liana-with-growthstack' ) }
				label={ __( 'LianaMailer Consent', 'liana-with-growthstack' ) }
				options={ consentOptions }
				onChange={ ( value ) =>
					setFormStateSettings( (prevState) => {
						return {
							...prevState,
							consent: value,
						};
					} )
				}
				value={ formStateSettings?.consent || '' }
			/>
		);

	}, [ data?.fields.length, formStateSettings, lianaMailerConsents ] );

	const checkConsents = useCallback( async ( site ) => {
		if ( ! lianaMailerConsents[ site ] ) {
			await fetchLianaMailerData( proxyEndpoint, `getConsentTypesBySite?arg=${ site }` )
			.then( ( result ) => {
				if ( result && result.data ) {
					setLianaMailerConsents( {
						...lianaMailerConsents,
						[ site ]: result.data,
					} );
				}
			} )
			.catch( () => {
				showNotice(
					'error',
					__( 'Error fetching LianaMailer consent types.', 'liana-with-growthstack' ),
				);
			} );
		}
	}, [ lianaMailerConsents, proxyEndpoint, showNotice ] );

	// Fetch consents when site changes and when form is opened with a site already selected.
	useEffect( () => {
		if ( formStateSettings?.site ) {
			checkConsents( formStateSettings.site );
		}
	}, [ formStateSettings?.site, checkConsents ] );

	const handleSiteChange = useCallback( async ( site: string ) => {
		const siteData = lianaMailerData[ site ] ?? {};
		const additionalSettings = {
			welcome: siteData?.welcome ?? false,
			registration_needs_confirmation:
				siteData?.need_confirmation ?? false,
		};

		setFormStateSettings( ( prevState ) => ( {
			...prevState,
			site,
			additional_settings: additionalSettings,
			lists: '', // Reset list when site changes
		} ) );
		possiblyPopulateEmail();
	}, [ possiblyPopulateEmail, lianaMailerData ] );

	const emailError = useMemo(
		() => {
			if ( ! errorFields.includes( 'email' ) ) {
				return null;
			}
			return (
				<Message
					header={ __( 'Error', 'liana-with-growthstack' ) }
					content={ __( 'One of your form fields should be mapped to email for LianaMailer integration to work.', 'liana-with-growthstack' ) }
					type="error"
				/>
			);
		},
		[ errorFields ]
	);

	const noFieldsWarning = useMemo(
		() => {
			if ( data?.fields.length > 0 ) {
				return null;
			}
			return (
				<Message
					header={ __( 'Create fields for your form', 'liana-with-growthstack' ) }
					content={ (
						<>
							{ __( 'Your form doesn\'t have any fields yet. Please add some fields to the form first.', 'liana-with-growthstack' ) }
							{ ' ' }
							<a href={ data?.url } target="_blank" rel="noreferrer">
								{ __( 'Edit form', 'liana-with-growthstack' ) }
							</a>
						</>
					) }
					type="warning"
				/>
			);
		},
		[ data?.fields.length, data?.url ]
	);

	// Add a disabled mailing lists field to the form if list choices field is selected and mailing lists field does not exist yet.
	const mailingListsField = useMemo(
		() => {
			const choicesFieldExists = data?.fields.find( ( field ) => field?.list_choices_field );
			if ( formStateSettings?.list_choices_field && ! choicesFieldExists && formStateSettings?.lists.length > 1 ) {
				return (
					<SelectControl
						className="gs-select-control"
						disabled={ true }
						label={ __( 'Mailing Lists [checkbox] (added automatically)', 'liana-with-growthstack' ) }
						onChange={ () => {} }
						options={ propertyOptions }
						value="lianamailer_mailinglists"
					/>
				);
			}
			return null;
		},
		[ data?.fields, formStateSettings?.list_choices_field, formStateSettings?.lists, propertyOptions ]
	);

	// Check if any fields have sub-fields (e.g., split GF name field).
	const hasNameSubfields = useMemo(
		() => data?.fields?.some( ( field ) => field?.has_subfields ),
		[ data?.fields ]
	);

	const onSplitNameFieldsChange = useCallback( ( event ) => {
		const checked = event?.target?.checked;
		setFormStateSettings( ( prevState ) => {
			// Clear property mappings for fields that will be hidden.
			const cleanedProperties = { ...( prevState.properties || {} ) };
			data?.fields?.forEach( ( field ) => {
				if ( checked && field?.has_subfields ) {
					// Switching to split: clear parent name field mapping.
					delete cleanedProperties[ field.id ];
				}
				if ( ! checked && field?.parent_id ) {
					// Switching to combined: clear sub-field mappings.
					delete cleanedProperties[ field.id ];
				}
			} );
			return {
				...prevState,
				split_name_fields: checked,
				properties: cleanedProperties,
			};
		} );
	}, [ data?.fields ] );

	const propertySelects = useMemo(
		() => {
			let selects = data?.fields;
			if ( ! formStateSettings?.list_choices_field || formStateSettings?.lists.length <= 1 ) {
				selects = selects?.filter( ( field ) => ! field?.list_choices_field );
			}
			// Filter fields based on split name fields toggle.
			if ( formStateSettings?.split_name_fields ) {
				// Show sub-fields, hide parent name fields.
				selects = selects?.filter( ( field ) => ! field?.has_subfields );
			} else {
				// Show parent name fields, hide sub-fields.
				selects = selects?.filter( ( field ) => ! field?.parent_id );
			}
			return selects?.map( ( field ) => (
				<SelectControl
					className="gs-select-control"
					disabled={ ! formStateSettings?.enabled || ! formStateSettings?.site || field?.list_choices_field }
					key={ field.id }
					label={ `${ field.label } [${ field.type }]` }
					onChange={ ( value ) => onPropertyChange( field.id, value ) }
					options={ propertyOptions }
					value={
						formStateSettings?.properties?.[
							field.id
						] || ''
					}
				/>
			) );
		},
		[ data?.fields, formStateSettings, onPropertyChange, propertyOptions ]
	)

	return (
		<>
			{ isOpen && (
				<Modal
					className="gs-modal"
					title={ title }
					onRequestClose={ onClose }
					style={ {
						width: '100%',
						maxWidth: '920px',
					} }
				>
					{ loading && <Spinner /> }
					<div className="gs-modal__content gs-settings-form">
						<Toggle
							checked={ formStateSettings?.enabled || false }
							id="enabled"
							label={ __( 'LianaMailer enabled', 'liana-with-growthstack' ) }
							name="enabled"
							onChange={ ( event ) =>
								setFormStateSettings( (prevState) => {
									return {
										...prevState,
										enabled: event?.target.checked,
									};
								} )
							}
						/>
						<SelectControl
							className={`gs-select-control ${ errorFields.includes( 'site' ) ? 'gs-select-control--error' : ''}`}
							disabled={ ! formStateSettings?.enabled }
							label={
								<>
									{ __( 'Subscription site', 'liana-with-growthstack' ) }
									<Tooltip
										delay={ 50 }
										hideOnClick={ true }
										text={ __( 'Select a LianaMailer Subscription Site. This choice determines which mailing lists are available for subscription and which contact fields you can map the form data to.', 'liana-with-growthstack' ) }
									>
										<Icon icon="info" style={ { marginLeft: '4px' } } size={ 16 } />
									</Tooltip>
								</> }
							onChange={ ( value ) => handleSiteChange( value ) }
							options={ siteOptions }
							value={ formStateSettings?.site || '' }
						/>
						<LianaMailerListSelect { ...{ errorFields, formStateSettings, lianaMailerData, onListChange } } />
						{ formStateSettings?.enabled && formStateSettings?.lists.length > 1 && formStateSettings.plugin !== 'contactform7' && (
							<div className="gs-flex">
								<Toggle
									checked={ !! formStateSettings?.list_choices_field || false }
									id="list_choices_field"
									label={ __(
										'Let user choose which mailing lists to join in the form',
										'liana-with-growthstack'
									) }
									name="list_choices_field"
									onChange={ ( event ) => {
										const checked = event?.target.checked;
										const value   = checked ? 'true' : '';
										return setFormStateSettings( (prevState) => {
											return {
												...prevState,
												list_choices_field:
													value,
											};
										} )
									} }
									value={ formStateSettings?.list_choices_field || 'true' }
								/>
								<Tooltip
									delay={ 50 }
									hideOnClick={ true }
									text={ __( 'Checkbox field is appended to the form. Choices are populated with mailing list IDs as their values and list names as their labels. You can edit the field in the form edit view after saving.', 'liana-with-growthstack' ) }
								>
									<Icon icon="info" size={ 16 } />
								</Tooltip>
							</div>
						) }
						{ formStateSettings && formStateSettings.site && formStateSettings.lists.length > 1 && formStateSettings.plugin === 'contactform7' && (
							<p className="">
								<Icon icon="info" style={ { marginRight: '4px' } } />
								{ __( 'For users to be able to choose which mailing lists to join, add this tag to your form template', 'liana-with-growthstack' ) }
								: <Tooltip delay={ 0 } placement="top" hideOnClick={ false } text={ cf7Tooltip }><button type="button" className="gs-code-tag copyable" onClick={ copyTag }>{ cf7ListsTag }</button></Tooltip>
							</p>
						) }
						{ optInField }
						{ lianaConsentField }
						<h3>{ __( 'Field Mapping', 'liana-with-growthstack' ) }
							<Tooltip
								delay={ 50 }
								hideOnClick={ true }
								text={ __( "Only properties added to the selected Subscription Site in LianaMailer will appear here. If a property is missing, you must either select a different Subscription Site or update the current site's property list in LianaMailer settings.", 'liana-with-growthstack' ) }
							>
								<Icon icon="info" style={ { marginLeft: '4px' } } size={ 16 } />
							</Tooltip>
						</h3>
						<p>{ __( 'Select corresponding LianaMailer fields for your data. Email is mandatory for the integration to work.', 'liana-with-growthstack' ) }</p>
						{ hasNameSubfields && (
							<Toggle
								checked={ !! formStateSettings?.split_name_fields }
								disabled={ ! formStateSettings?.enabled || ! formStateSettings?.site }
								id="split_name_fields"
								label={ __( 'Map name field parts separately', 'liana-with-growthstack' ) }
								name="split_name_fields"
								onChange={ onSplitNameFieldsChange }
							/>
						) }
						{ emailError }
						{ noFieldsWarning }
						{ propertySelects }
						{ mailingListsField }
					</div>
					<div className="gs-modal__actions">
						<Button variant="secondary" onClick={ onClose }>
							{ __( 'Cancel', 'liana-with-growthstack' ) }
						</Button>
						<Button
							disabled={ loading || ! hasChanges }
							variant="primary"
							onClick={ () => onSave( formStateSettings ) }
						>
							{ loading
								? __( 'Saving…', 'liana-with-growthstack' )
								: __( 'Save', 'liana-with-growthstack' ) }
						</Button>
					</div>
				</Modal>
			) }
		</>
	);
}
