/**
 * External dependencies,
 */
import { addFilter } from '@wordpress/hooks';

/**
 * Internal dependencies.
 */
import { ExpirySettings, TimerSettings } from './controls';
import { getEvergreenEndDate } from './helpers';

/**
 * Extends block attributes for the Spectra Countdown block.
 *
 * @since x.x.x
 *
 * @param {Object} settings Block settings.
 * @param {string} name     Block name.
 * @return {Object} Modified block settings with additional attributes.
 */
const addAttributes = ( settings, name ) => {
	if ( name !== 'spectra/countdown' ) {
		return settings;
	}

	return {
		...settings,
		attributes: {
			...settings.attributes,
			timerEndAction: {
				type: 'string',
				default: 'zero',
			},
			redirectURL: {
				type: 'string',
				default: '',
			},
			reloadRequired: {
				type: 'boolean',
				default: true,
			},
			autoReload: {
				type: 'boolean',
				default: false,
			},
			evergreenDays: {
				type: 'number',
				default: 0,
			},
			evergreenHours: {
				type: 'number',
				default: 0,
			},
			evergreenMinutes: {
				type: 'number',
				default: 0,
			},
			uniqueId: {
				type: 'string',
			},
			resetAfterDays: {
				type: 'number',
				default: 1,
			},
			editorInnerBlocksPreview: {
				type: 'boolean',
				default: false,
			},
		},
	};
};

/**
 * Calculates the remaining time for an evergreen timer.
 *
 * @since x.x.x
 *
 * @param {Object}   defaultValue           Default time values.
 * @param {Object}   attributes             Block attributes.
 * @param {Function} calculateRemainingTime Function to calculate remaining time.
 * @return {Object} Calculated time or default value with expiration status.
 */
const calculateEvergreenTime = ( defaultValue, attributes, calculateRemainingTime ) => {
	const {
		timerType,
		evergreenDays = 0,
		evergreenHours = 0,
		evergreenMinutes = 0,
		showDays,
		showHours,
		showMinutes,
		showSeconds,
		uniqueId = '',
		resetAfterDays = 1,
	} = attributes;

	// Return default value for date-based timers or if calculateRemainingTime is missing.
	if ( timerType === 'date' || typeof calculateRemainingTime !== 'function' ) {
		return defaultValue;
	}

	// If all evergreen values are 0, return expired state.
	if ( evergreenDays === 0 && evergreenHours === 0 && evergreenMinutes === 0 ) {
		return {
			...defaultValue,
			days: 0,
			hours: 0,
			minutes: 0,
			seconds: 0,
			isExpired: true,
		};
	}

	// Calculate evergreen end date.
	const evergreenEndDateTime = getEvergreenEndDate(
		evergreenDays,
		evergreenHours,
		evergreenMinutes,
		uniqueId,
		resetAfterDays
	);

	// Validate evergreenEndDateTime.
	if ( ! evergreenEndDateTime || isNaN( new Date( evergreenEndDateTime ).getTime() ) ) {
		return {
			...defaultValue,
			days: 0,
			hours: 0,
			minutes: 0,
			seconds: 0,
			isExpired: true,
		};
	}

	// Calculate remaining time for evergreen timer.
	return calculateRemainingTime( evergreenEndDateTime, showDays, showHours, showMinutes, showSeconds );
};

/**
 * Extends the reset all attributes for the countdown block.
 *
 * @since x.x.x
 *
 * @return {Object} Additional attributes to reset.
 */
const addResetAllAttributes = () => {
	return {
		timerEndAction: 'zero',
		redirectURL: '',
		autoReload: false,
		evergreenDays: 0,
		evergreenHours: 0,
		evergreenMinutes: 0,
		resetAfterDays: 1,
	};
};

/**
 * Extends the dependencies for calculateTime memoization.
 * Adds Pro-specific dependencies like evergreen settings to ensure accurate memoization.
 *
 * @since x.x.x
 *
 * @param {Object} deps       Current dependencies.
 * @param {Object} attributes Block attributes.
 * @return {Object} Extended dependencies.
 */
const extendCalculateTimeDependencies = ( deps, attributes ) => {
	const { evergreenDays, evergreenHours, evergreenMinutes } = attributes;

	return {
		...deps,
		evergreenDays,
		evergreenHours,
		evergreenMinutes,
	};
};

/**
 * Adds timer settings controls to the Spectra Countdown block.
 */
addFilter( 'spectra.countdown.timer-settings', 'spectra-pro/countdown/add-timer-settings', TimerSettings );

/**
 * Adds expiry settings controls to the Spectra Countdown block.
 */
addFilter( 'spectra.countdown.expiry-settings', 'spectra-pro/countdown/add-expiry-settings', ExpirySettings );

/**
 * Registers additional attributes for the Spectra Countdown block.
 */
addFilter( 'blocks.registerBlockType', 'spectra-pro/countdown/add-attributes', addAttributes );

/**
 * Modifies the time calculation logic for evergreen timers in the Spectra Countdown block.
 */
addFilter( 'spectra.countdown.calculateTime', 'spectra-pro/countdown/add-calculate-time', calculateEvergreenTime );

/**
 * Extends the reset attributes functionality for the Spectra Countdown block.
 */
addFilter(
	'spectra.countdown.reset-all-attributes',
	'spectra-pro/countdown/add-reset-all-attributes',
	addResetAllAttributes
);

/**
 * Extends the dependencies for calculateTime memoization for the Spectra Countdown block.
 */
addFilter(
	'spectra.countdown.calculateTime.dependencies',
	'spectra-pro/countdown/extend-calculate-deps',
	extendCalculateTimeDependencies
);
