import { CompactCard, Count } from '@automattic/components';
import clsx from 'clsx';
import { localize } from 'i18n-calypso';
import { uniqBy } from 'lodash';
import PropTypes from 'prop-types';
import { Component } from 'react';
import { connect } from 'react-redux';
import FormInputCheckbox from 'calypso/components/forms/form-checkbox';
import { withLocalizedMoment } from 'calypso/components/localized-moment';
import Notice from 'calypso/components/notice';
import {
	ACTIVATE_PLUGIN,
	DEACTIVATE_PLUGIN,
	DISABLE_AUTOUPDATE_PLUGIN,
	ENABLE_AUTOUPDATE_PLUGIN,
	REMOVE_PLUGIN,
	UPDATE_PLUGIN,
} from 'calypso/lib/plugins/constants';
import PluginActivateToggle from 'calypso/my-sites/plugins/plugin-activate-toggle';
import PluginAutoupdateToggle from 'calypso/my-sites/plugins/plugin-autoupdate-toggle';
import PluginIcon from 'calypso/my-sites/plugins/plugin-icon/plugin-icon';
import { siteObjectsToSiteIds } from 'calypso/my-sites/plugins/utils';
import { getPluginOnSites } from 'calypso/state/plugins/installed/selectors';
import { isMarketplaceProduct } from 'calypso/state/products-list/selectors';

import './style.scss';

class PluginItem extends Component {
	static propTypes = {
		plugin: PropTypes.object,
		sites: PropTypes.array,
		isSelected: PropTypes.bool,
		isSelectable: PropTypes.bool,
		onClick: PropTypes.func,
		pluginLink: PropTypes.string,
		allowedActions: PropTypes.shape( {
			activation: PropTypes.bool,
			autoupdate: PropTypes.bool,
		} ),
		isAutoManaged: PropTypes.bool,
		progress: PropTypes.array,
	};

	static defaultProps = {
		allowedActions: {
			activation: true,
			autoupdate: true,
		},
		progress: [],
		isAutoManaged: false,
	};

	ago( date ) {
		return this.props.moment.utc( date, 'YYYY-MM-DD hh:mma' ).fromNow();
	}

	doing() {
		const { translate, progress } = this.props;
		const log = progress[ 0 ];
		const uniqLogs = uniqBy( progress, function ( uniqLog ) {
			return uniqLog.siteId;
		} );
		const translationArgs = {
			args: { count: uniqLogs.length },
			count: uniqLogs.length,
		};

		let message;
		switch ( log && log.action ) {
			case UPDATE_PLUGIN:
				message = this.props.selectedSite
					? translate( 'Updating', { context: 'plugin' } )
					: translate(
							'Updating on %(count)s site',
							'Updating on %(count)s sites',
							translationArgs
					  );
				break;

			case ACTIVATE_PLUGIN:
				message = this.props.selectedSite
					? translate( 'Activating', { context: 'plugin' } )
					: translate(
							'Activating on %(count)s site',
							'Activating on %(count)s sites',
							translationArgs
					  );
				break;

			case DEACTIVATE_PLUGIN:
				message = this.props.selectedSite
					? translate( 'Deactivating', { context: 'plugin' } )
					: translate(
							'Deactivating on %(count)s site',
							'Deactivating on %(count)s sites',
							translationArgs
					  );
				break;

			case ENABLE_AUTOUPDATE_PLUGIN:
				message = this.props.selectedSite
					? translate( 'Enabling autoupdates' )
					: translate(
							'Enabling autoupdates on %(count)s site',
							'Enabling autoupdates on %(count)s sites',
							translationArgs
					  );
				break;

			case DISABLE_AUTOUPDATE_PLUGIN:
				message = this.props.selectedSite
					? translate( 'Disabling autoupdates' )
					: translate(
							'Disabling autoupdates on %(count)s site',
							'Disabling autoupdates on %(count)s sites',
							translationArgs
					  );

				break;
			case REMOVE_PLUGIN:
				message = this.props.selectedSite
					? translate( 'Removing' )
					: translate(
							'Removing from %(count)s site',
							'Removing from %(count)s sites',
							translationArgs
					  );
		}
		return message;
	}

	renderUpdateFlag() {
		const { pluginsOnSites, sites, translate } = this.props;
		const recentlyUpdated = sites.some( function ( site ) {
			const sitePlugin = pluginsOnSites?.sites[ site.ID ];
			return sitePlugin?.update?.recentlyUpdated;
		} );

		if ( recentlyUpdated ) {
			return (
				<Notice
					isCompact
					icon="checkmark"
					status="is-success"
					inline
					text={ translate( 'Updated' ) }
				/>
			);
		}

		const updated_versions = sites
			.map( ( site ) => {
				const sitePlugin = pluginsOnSites?.sites[ site.ID ];
				return sitePlugin?.update?.new_version;
			} )
			.filter( ( version ) => version );

		return (
			<Notice
				isCompact
				icon="sync"
				inline
				text={ translate( 'Version %(newPluginVersion)s is available', {
					args: { newPluginVersion: updated_versions[ 0 ] },
				} ) }
			/>
		);
	}

	hasUpdate() {
		const { pluginsOnSites, sites } = this.props;

		return sites.some( ( site ) => {
			const sitePlugin = pluginsOnSites?.sites[ site.ID ];
			return sitePlugin?.update && site.canUpdateFiles;
		} );
	}

	pluginMeta( pluginData ) {
		const { progress, translate } = this.props;
		if ( progress.length ) {
			const message = this.doing();
			if ( message ) {
				return <Notice isCompact status="is-info" text={ message } inline />;
			}
		}
		if ( this.props.isAutoManaged ) {
			return (
				<div className="plugin-item__last-updated">
					{ translate( 'Auto-managed on this site' ) }
				</div>
			);
		}

		if ( this.hasUpdate() ) {
			return this.renderUpdateFlag();
		}

		if ( pluginData.last_updated ) {
			return (
				<div className="plugin-item__last-updated">
					{ translate( 'Last updated %(ago)s', {
						args: { ago: this.ago( pluginData.last_updated ) },
					} ) }
				</div>
			);
		}

		return null;
	}

	renderActions() {
		const { activation: canToggleActivation, autoupdate: canToggleAutoupdate } =
			this.props.allowedActions;

		return (
			<div className="plugin-item__actions">
				{ canToggleActivation && (
					<PluginActivateToggle
						plugin={ this.props.plugin }
						disabled={ this.props.isSelectable }
						site={ this.props.selectedSite }
					/>
				) }
				{ canToggleAutoupdate && (
					<PluginAutoupdateToggle
						plugin={ this.props.plugin }
						disabled={ this.props.isSelectable }
						site={ this.props.selectedSite }
						wporg={ !! this.props.plugin.wporg }
						isMarketplaceProduct={ this.props.isMarketplaceProduct }
					/>
				) }
			</div>
		);
	}

	renderSiteCount() {
		const { sites, translate } = this.props;
		return (
			<div className="plugin-item__count">
				{ translate( 'Sites {{count/}}', {
					components: {
						count: <Count count={ sites.length } />,
					},
				} ) }
			</div>
		);
	}

	renderPlaceholder() {
		return (
			// eslint-disable-next-line wpcalypso/jsx-classname-namespace
			<CompactCard className="plugin-item is-placeholder">
				<div className="plugin-item__link">
					<PluginIcon isPlaceholder />
					<div className="plugin-item__info">
						<div className="plugin-item__title is-placeholder" />
					</div>
				</div>
			</CompactCard>
		);
	}

	onItemClick = ( event ) => {
		if ( this.props.isSelectable ) {
			event.preventDefault();
			this.props.onClick( this );
		}
	};

	render() {
		const plugin = this.props.plugin;

		if ( ! plugin ) {
			return this.renderPlaceholder();
		}

		const pluginTitle = <div className="plugin-item__title">{ plugin.name }</div>;

		let pluginActions = null;
		if ( ! this.props.selectedSite ) {
			pluginActions = this.renderSiteCount();
		} else {
			pluginActions = this.renderActions();
		}

		const pluginItemClasses = clsx( 'plugin-item', 'plugin-item-' + plugin.slug );

		return (
			<CompactCard className={ pluginItemClasses }>
				{ ! this.props.isSelectable ? null : (
					<FormInputCheckbox
						className="plugin-item__checkbox"
						id={ plugin.slug }
						title={ plugin.name }
						onClick={ this.props.onClick }
						checked={ this.props.isSelected }
						readOnly
					/>
				) }
				<a
					className="plugin-item__link"
					href={ this.props.pluginLink }
					onClick={ this.onItemClick }
				>
					<PluginIcon image={ plugin.icon } />
					<div className="plugin-item__info">
						{ pluginTitle }
						{ this.pluginMeta( plugin ) }
					</div>
				</a>
				{ pluginActions }
			</CompactCard>
		);
	}
}

export default connect( ( state, { plugin, sites } ) => {
	const siteIds = siteObjectsToSiteIds( sites );

	return {
		pluginsOnSites: getPluginOnSites( state, siteIds, plugin?.slug ),
		isMarketplaceProduct: isMarketplaceProduct( state, plugin?.slug ),
	};
} )( localize( withLocalizedMoment( PluginItem ) ) );
