/**
 * WordPress provides React during the page load. This is for TypeScript type checking only.
 *
 * Importing React from @wordpress/element causes "Cannot read property 'createElement' of undefined"
 */
import React from 'react';

import { withSelect } from '@wordpress/data';
import { ASMSelectControl, ASMSelectControlItem, ASMSelectControlProps } from '../../components/controls-inspector/sidebar/ASMSelectControl';
import { TextareaControl, TextControl, ToggleControl, SelectControl } from '@wordpress/components';
import { __ } from '@wordpress/i18n';

interface SummaryColumnsControlProps extends BlockProps< any > {
	label: string;
}

function SummaryColumnOptions( props: { item: ASMSelectControlItem, meta: ASMSelectControlItem[ 'meta' ], setMeta: ( meta: ASMSelectControlItem[ 'meta' ] ) => void } ) : JSX.Element {
	const { item, meta, setMeta } = props;

	return <>
		<TextControl
			value={ meta?.label }
			onChange={ ( value ) =>
				setMeta( { ...meta, label: value } )
			}
			label={ item.labelRequired ? __( 'Label', 'gp-entry-blocks' ) : __( 'Custom Label', 'gp-entry-blocks' ) }
		/>

		{
			item?.allowLinkToEntry ? <>
				<br />
				<ToggleControl
					checked={ meta?.linkToEntry }
					onChange={ ( state ) =>
						setMeta( { ...meta, linkToEntry: state } )
					}
					label={ __( 'Link to Entry', 'gp-entry-blocks' ) }
				/>
			</> : undefined
		}

		{
			item?.allowSorting
				? <>
					<br />
					<ToggleControl
						checked={ meta?.allowSorting }
						onChange={ ( state ) =>
							setMeta( { ...meta, allowSorting: state } )
						}
						label={ __( 'Allow Sorting', 'gp-entry-blocks' ) }
					/>
					{ meta?.allowSorting && item.sortingInputs?.length ? <SelectControl
						label={ __( 'Sorting Input', 'gp-entry-blocks' ) }
						value={ meta?.sortingId }
						options={ item.sortingInputs.map( ( input ) => ( {
							label: input.label,
							value: input.id,
						} ) ) }
						onChange={ ( val ) => {
							setMeta( { ...meta, sortingId: val } );
						} }
					/> : undefined }
				</> : undefined
		}
	</>;
}

function CustomColumnOptions( props: { item: ASMSelectControlItem, meta: ASMSelectControlItem[ 'meta' ], setMeta: ( meta: ASMSelectControlItem[ 'meta' ] ) => void } ) : JSX.Element {
	const { item, meta, setMeta } = props;

	return <>
		<TextareaControl
			value={ meta?.content }
			onChange={ ( value ) =>
				setMeta( { ...meta, content: value } )
			}
			label={ __( 'Content', 'gp-entry-blocks' ) }
			help={ __( 'Gravity Forms merge tags can be used here.', 'gp-entry-blocks' ) }
		/>
	</>;
}

function LinkColumnOptions( props: { item: ASMSelectControlItem, meta: ASMSelectControlItem[ 'meta' ], setMeta: ( meta: ASMSelectControlItem[ 'meta' ] ) => void } ) : JSX.Element {
	const { item, meta, setMeta } = props;

	return <>
		<TextControl
			value={ meta?.linkLabel }
			onChange={ ( value ) =>
				setMeta( { ...meta, linkLabel: value } )
			}
			label={ __( 'Link Label', 'gp-entry-blocks' ) }
		/>
	</>;
}

function SummaryColumnsControl(
	props: SummaryColumnsControlProps & {
		formFields: {
			id: string
			label: string,
			displayOnly: boolean,
			type: string,
			[ key: string ]: any
			inputs: any,
		}[]
		formMeta: {
			key: string
			label: string
		}[]
	}
) {
	function onChange( val ) {
		props.setAttributes( { formFields: val } );
	}

	const formInputs: ASMSelectControlProps[ 'items' ] = [];

	for ( const formField of props.formFields ) {
		if ( formField.displayOnly ) {
			continue;
		}

		formInputs.push( {
			type: 'field',
			allowMultiple: 'fieldId',
			meta: {
				fieldId: formField.id,
				// Default Name fields to the First name field for sorting.
				// @todo Make this more robust, possibly feed in from AJAX endpoint.
				sortingId: formField.type === 'name' ? `${ formField.id }.3` : undefined,
			},
			label: formField.label,
			sortingInputs: formField.inputs,
			group: __( 'Fields', 'gp-entry-blocks' ),
			allowSorting: true,
			// @todo Add filter to allow more fields to be linked to if they have multiple inputs.
			allowLinkToEntry: formField.type === 'name' || ! formField.inputs,
		} );

		if ( formField.inputs ) {
			for ( const input of formField.inputs ) {
				formInputs.push( {
					type: 'field',
					allowMultiple: 'fieldId',
					meta: {
						fieldId: input.id,
						sortingId: input.id,
					},
					label: formField.label + ' (' + input.label + ')',
					optionLabel: '\xa0\xa0\xa0\xa0' + input.label,
					group: __( 'Fields', 'gp-entry-blocks' ),
					allowSorting: true,
					allowLinkToEntry: true,
				} );
			}
		}
	}

	const items: ASMSelectControlProps[ 'items' ] = [
		{
			type: 'custom',
			label: __( 'Custom', 'gp-entry-blocks' ),
			labelRequired: true,
			allowMultiple: true,
			customOptions: CustomColumnOptions,
		},
		{
			type: 'id',
			label: __( 'Entry ID', 'gp-entry-blocks' ),
			allowSorting: true,
			allowLinkToEntry: true,
		},
		{
			type: 'created_by',
			label: __( 'Created By', 'gp-entry-blocks' ),
			allowLinkToEntry: true,
		},
		{
			type: 'date_created',
			label: __( 'Date Created', 'gp-entry-blocks' ),
			allowSorting: true,
			allowLinkToEntry: true,
		},
		{
			type: 'date_updated',
			label: __( 'Date Updated', 'gp-entry-blocks' ),
			allowSorting: true,
			allowLinkToEntry: true,
		},
		{
			type: 'ip',
			label: __( 'IP', 'gp-entry-blocks' ),
			allowLinkToEntry: true,
		},
		{
			type: 'payment_method',
			label: __( 'Payment Method', 'gp-entry-blocks' ),
			allowSorting: true,
			allowLinkToEntry: true,
		},
		{
			type: 'payment_status',
			label: __( 'Payment Status', 'gp-entry-blocks' ),
			allowSorting: true,
			allowLinkToEntry: true,
		},
		{
			type: 'transaction_id',
			label: __( 'Transaction ID', 'gp-entry-blocks' ),
			allowLinkToEntry: true,
		},
		// @todo switch these links to underscores to make them consistent with other columns
		{
			type: 'edit-link',
			label: __( 'Edit Link', 'gp-entry-blocks' ),
			group: __( 'Actions', 'gp-entry-blocks' ),
			customOptions: LinkColumnOptions,
		},
		{
			type: 'view-link',
			label: __( 'View Link', 'gp-entry-blocks' ),
			group: __( 'Actions', 'gp-entry-blocks' ),
			customOptions: LinkColumnOptions,
		},
		{
			type: 'delete-link',
			label: __( 'Delete Link', 'gp-entry-blocks' ),
			group: __( 'Actions', 'gp-entry-blocks' ),
			customOptions: LinkColumnOptions,
		},
		{
			type: 'duplicate-link',
			label: __( 'Duplicate Link', 'gp-entry-blocks' ),
			group: __( 'Actions', 'gp-entry-blocks' ),
			customOptions: LinkColumnOptions,
		},
		...formInputs,
		...props.formMeta.map( ( formMeta ) => {
			return {
				type: 'meta',
				allowMultiple: 'metaKey',
				meta: {
					metaKey: formMeta.key,
				},
				label: formMeta.label,
				group: __( 'Entry Meta', 'gp-entry-blocks' ),
				allowSorting: true,
				allowLinkToEntry: true,
			};
		} ),
	].filter( Boolean );

	return (
		<ASMSelectControl
			onChange={ onChange }
			items={ items }
			placeholder={ __( 'Select a Column', 'gp-entry-blocks' ) }
			value={ props.attributes.formFields ?? [] }
			label={ props.label }
			id="gpeb-entries-table-field-selector"
			itemOptions={ SummaryColumnOptions }
			itemOptionsModalTitle={ __( 'Summary Column Options', 'gp-entry-blocks' ) }
		/>
	);
}

export default withSelect<
	{ formFields: { id: string; label: string }[] },
	SummaryColumnsControlProps
>( ( select, ownProps ) => {
	return {
		formFields: select( 'gp-entry-blocks' ).getFormFields(
			ownProps.context[ 'gp-entry-blocks/formId' ]
		),
		formMeta: select( 'gp-entry-blocks' ).getFormMeta(
			ownProps.context[ 'gp-entry-blocks/formId' ]
		),
	};
} )( SummaryColumnsControl );
