import {
	ToggleControl,
	PanelBody,
	PanelRow,
	RadioControl,
	Notice,
} from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { __, sprintf } from '@wordpress/i18n';
import './style.pcss';
import { storeName } from '../store/constants';
import { memo } from 'react';
import { useEntityProp } from '@wordpress/core-data';
import { metaKeys, subscribers, tableUrl } from '../store/constants';
import { EVENT } from '@tec/common/data/editor';

/**
 * Get the text for the given type.
 *
 * @since 6.2.0
 * @param {string} text The text to get.
 * @param {string} type The type of text to get.
 * @returns {string} The text.
 */
const getText = ( text, type ) => {
	const texts = {
		label : {
			tickets: __( 'Notify people when tickets become available for your event.', 'event-tickets-plus' ),
			rsvp: __( 'Notify people when RSVPs become available for your event.', 'event-tickets-plus' ),
		},
		alwaysLabel: {
			tickets: __( 'WHEN TICKETS ARE ON PRE-SALE OR SOLD OUT', 'event-tickets-plus' ),
			rsvp: __( 'WHEN RSVP IS ON PRE-SALE OR AT MAXIMUM CAPACITY', 'event-tickets-plus' ),
		},
		beforeSaleLabel: {
			tickets: __( 'BEFORE TICKETS GO ON SALE', 'event-tickets-plus' ),
			rsvp: __( 'BEFORE RSVP STARTS', 'event-tickets-plus' ),
		},
		onSoldOutLabel: {
			tickets: __( 'WHEN TICKETS ARE SOLD OUT', 'event-tickets-plus' ),
			rsvp: __( 'WHEN RSVP REACHES MAXIMUM CAPACITY', 'event-tickets-plus' ),
		},
		alwaysDesc: {
			tickets: __( 'Shows before tickets go on sale and when tickets are sold out', 'event-tickets-plus' ),
			rsvp: __( 'Shows before RSVP start date and after RSVP reaches maximum capacity', 'event-tickets-plus'),
		},
		beforeSaleDesc: {
			tickets: __( 'Shows until tickets sale start date', 'event-tickets-plus' ),
			rsvp: __( 'Shows until RSVP start date', 'event-tickets-plus' ),
		},
		onSoldOutDesc: {
			tickets: __( 'Shows when ticket capacity runs out', 'event-tickets-plus' ),
			rsvp: __( 'Shows when RSVP capacity runs out', 'event-tickets-plus' ),
		},
		notice: {
			tickets: __( 'To create a waitlist you need to have existing tickets.', 'event-tickets-plus' ),
			rsvp: __( 'To create a waitlist you need to have an existing RSVP.', 'event-tickets-plus' ),
		},
		ascNotice: {
			tickets: __( 'The waitlist functionality is not yet available in combination with Assigned Seating.', 'event-tickets-plus' ),
			rsvp: __( 'The waitlist functionality is not yet available in combination with Assigned Seating.', 'event-tickets-plus' ),
		},
		waitlistActivePlural: {
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			tickets: __( 'The waitlist is currently active. There are %s%d registrants%s.', 'event-tickets-plus' ),
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			rsvp: __( 'The waitlist is currently active. There are %s%d registrants%s.', 'event-tickets-plus' ),
		},
		waitlistActiveSingular: {
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			tickets: __( 'The waitlist is currently active. There is %s%d registrant%s.', 'event-tickets-plus' ),
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			rsvp: __( 'The waitlist is currently active. There is %s%d registrant%s.', 'event-tickets-plus' ),
		},
		waitlistEndedPlural: {
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			tickets: __( 'This waitlist has ended. There are %s%d registrants%s.', 'event-tickets-plus' ),
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			rsvp: __( 'This waitlist has ended. There are %s%d registrants%s.', 'event-tickets-plus' ),
		},
		waitlistEndedSingular: {
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			tickets: __( 'This waitlist has ended. There is %s%d registrant%s.', 'event-tickets-plus' ),
			// translators: 1) Opening a tag, 2) the number of registrants and 3) closing a tag.
			rsvp: __( 'This waitlist has ended. There is %s%d registrant%s.', 'event-tickets-plus' ),
		},
	};

	return texts[text][type];
};

/**
 * Displays a notice when there are no tickets.
 *
 * @since 6.2.0
 * @param {Object} props The component props.
 * @returns {Object} The component.
 */
const NoTicketsWarning = ( { hasTickets, type } ) => {
	if ( hasTickets ) {
		return;
	}

	return (
		<PanelRow>
			<Notice status="info" isDismissible={false}>
				{ getText('notice', type) }
			</Notice>
		</PanelRow>
	);
};

/**
 * Displays a notice when assigned seating is enabled.
 *
 * @since 6.2.0
 * @param {Object} props The component props.
 * @returns {Object} The component.
 */
const UsingAscWarning = ( { isUsingAssignedSeating, type } ) => {
	if ( ! isUsingAssignedSeating ) {
		return;
	}

	return (
		<PanelRow>
			<Notice status="info" isDismissible={false}>
				{ getText('ascNotice', type) }
			</Notice>
		</PanelRow>
	);
};

/**
 * Displays a label with a description.
 *
 * @since 6.2.0
 * @param {Object} props The component props.
 * @returns {Object} The component.
 */
const LabelWithDescription = ( { label, description } ) => {
	return (
		<div>
			<strong>{ label }</strong>
			<p>{ description }</p>
		</div>
	);
};

/**
 * Displays a notice when the waitlist has ended.
 *
 * @since 6.2.0
 * @param {Object} props The component
 * @returns {Object} The component.
 */
const WaitlistEndedNotice = ( { hasEnded, type } ) => {
	if ( ! hasEnded ) {
		return;
	}

	const text = 1 === subscribers[type] ? getText('waitlistEndedSingular', type) : getText('waitlistEndedPlural', type);

	const text_parts = text.split( '%s' );

	return (
		<PanelRow>
			<Notice status="info" isDismissible={false}>
				{ text_parts[0] }
				<a href={ tableUrl } target="_blank">
					{ sprintf( text_parts[1], subscribers[type] ) }
				</a>
				{ text_parts[2] }
			</Notice>
		</PanelRow>
	);
};

/**
 * Displays a notice when the waitlist is active.
 *
 * @since 6.2.0
 * @param {Object} props The component
 * @returns {Object} The component.
 */
export const WaitlistActiveNotice = ( { type } ) => {
	const text = 1 === subscribers[type] ? getText('waitlistActiveSingular', type) : getText('waitlistActivePlural', type);

	const text_parts = text.split( '%s' );

	return (
		<PanelRow className={'tec-tickets-plus-waitlist__waitlist-active-notice'}>
			<Notice status="info" isDismissible={false}>
				{ text_parts[0] }
				<a href={ tableUrl } target="_blank">
					{ sprintf( text_parts[1], subscribers[type] ) }
				</a>
				{ text_parts[2] }
			</Notice>
		</PanelRow>
	);
};

/**
 * The RSVP Notice Container.
 *
 * @since 6.2.0
 * @param {Object} props The component props.
 * @returns {Object} The component.
 */
export const RSVPNoticeContainer = ( { children } ) => {
	return (
		<div className={'tec-tickets-plus-waitlist__rsvp-notice-container'}>
			{ children }
		</div>
	);
};

/**
 * The Waitlist panel.
 *
 * @since 6.2.0
 * @param {Object} props The component props.
 * @returns {Object} The component.
 */
export const Panel = memo( ( { type } ) => {
	const {
		hasTickets,
		postType,
		postId,
		isWaitlistEnabled,
		selectedConditional,
		isUsingAssignedSeating,
		hasEnded
	} = useSelect( ( select ) => {
		return {
			hasTickets: select( storeName ).hasTickets( type ),
			isWaitlistEnabled: select( storeName ).isWaitlistEnabled( type ),
			selectedConditional: select( storeName ).getWaitlistConditional( type ),
			postType: select( 'core/editor' ).getCurrentPostType(),
			postId: select( 'core/editor' ).getCurrentPostId(),
			isUsingAssignedSeating: select( storeName ).isUsingAssignedSeating(),
			hasEnded: select( storeName ).hasWaitlistEnded( type ),
		}
	});

	const isTECEvent = postType === EVENT;

	const { setWaitlistStatus, setWaitlistConditional } = useDispatch( storeName );

	const [meta, setMeta] = useEntityProp('postType', postType, 'meta', postId);

	const onToggleChange = (checked) => {
		setWaitlistStatus(checked, type);

		const newMeta = {
			...meta,
			[metaKeys[type].enabled]: checked ? '1' : '0',
			// make sure we set this whenever the waitlist is toggle, in case its not set already.
			[metaKeys[type].conditional]: selectedConditional,
		};

		setMeta( newMeta );
	};

	const onChangeConditional = (value) => {
		setWaitlistConditional(value, type);
		const newMeta = {
			...meta,
			[metaKeys[type].conditional]: value,
		};
		setMeta(newMeta);
	};

	const isAvailable = isWaitlistEnabled && hasTickets && ! isUsingAssignedSeating;

	return (
		<PanelBody title={__('Waitlist', 'event-tickets-plus')} className="tec-tickets-plus-waitlist__panel-body">
			<PanelRow>
				<p>
					{ getText('label', type) }
				</p>
			</PanelRow>
			<NoTicketsWarning hasTickets={ hasTickets } type={ type } />
			<UsingAscWarning isUsingAssignedSeating={ isUsingAssignedSeating } type={ type } />
			<PanelRow>
				<ToggleControl
					label={ __( 'Enable Waitlist', 'event-tickets-plus' ) }
					onChange={ onToggleChange }
					disabled={ ! hasTickets || isUsingAssignedSeating }
					checked={ isAvailable }
				/>
			</PanelRow>
			{ isAvailable && (
				<>
					<PanelRow>
						<p><strong>{__( 'SHOW', 'event-tickets-plus')}</strong></p>
					</PanelRow>
					<PanelRow>
						<RadioControl
							help={ isTECEvent ? __( 'The waitlist will no longer show after the start of the event.', 'event-tickets-plus' ) : '' }
							selected={ selectedConditional || 'always' } // Default to always.
							options={ [
								{ label: <LabelWithDescription label={ getText('alwaysLabel', type) } description={ getText('alwaysDesc', type) }/>, value: metaKeys.conditionals.always },
								{ label: <LabelWithDescription label={ getText('beforeSaleLabel', type) } description={ getText('beforeSaleDesc', type) }/>, value: metaKeys.conditionals.before_sale },
								{ label: <LabelWithDescription label={ getText('onSoldOutLabel', type) } description={ getText('onSoldOutDesc', type) }/>, value: metaKeys.conditionals.on_sold_out },
							] }
							onChange={ onChangeConditional }
						/>
					</PanelRow>
				</>
			)}
			<WaitlistEndedNotice hasEnded={ hasEnded } type={ type } />
		</PanelBody>
	);
});
