/**
 * WordPress dependencies
 */
import {
	Dashicon,
	ToggleGroupControl,
	ToggleGroupControlOption,
} from '@safe-wordpress/components';
import { useSelect } from '@safe-wordpress/data';
import { createInterpolateElement, useState } from '@safe-wordpress/element';
import { _x, sprintf } from '@safe-wordpress/i18n';

/**
 * External dependencies
 */
import { store as NAB_DATA } from '@nab/data';
import { numberFormat } from '@nab/i18n';
import { EMPTY_OBJECT } from '@nab/utils';

/**
 * Internal dependencies
 */
import './style.scss';

import { ArpcChart } from './arpc-chart';
import { ArpcImprovementChart } from './arpc-improvement-chart';
import { ArpcTimelineChart } from './arpc-timeline-chart';
import { ConversionRatesChart } from './conversion-rates-chart';
import { ConversionRatesTimelineChart } from './conversion-rates-timeline-chart';
import { ViewsAndConversionsTimelineChart } from './views-and-conversions-timeline-chart';
import { ConversionImprovementChart } from './conversion-improvement-chart';
import { RevenueChart } from './revenue-chart';
import { RevenueImprovementChart } from './revenue-improvement-chart';
import { RevenueTimelineChart } from './revenue-timeline-chart';
import { getMoneyLabel, getNumberLabel } from '../utils';
import { useAreUniqueResultsVisible } from '../hooks';

type ChartType =
	| 'conversion-rate'
	| 'views-and-conversions'
	| 'revenue'
	| 'arpc';

export const EvolutionSection = (): JSX.Element => {
	const [ activeTimeline, setActiveTimeline ] =
		useState< ChartType >( 'conversion-rate' );

	return (
		<div className="nab-evolution-section">
			<div className="nab-evolution-section__header">
				<Title />
				<ChartSelector
					value={ activeTimeline }
					onChange={ setActiveTimeline }
				/>
			</div>
			<Summary />
			<TimelineChart type={ activeTimeline } />
			<ExtraCharts type={ activeTimeline } />
		</div>
	);
};

// ============
// HELPER VIEWS
// ============

const Title = () => (
	<h2>
		{ createInterpolateElement(
			sprintf(
				/* translators: %s: Dashicon. */
				_x( '%s Evolution', 'text', 'nelio-ab-testing' ),
				'<icon />'
			),
			{
				icon: (
					<Dashicon
						className="nab-evolution-section__title-icon"
						icon="chart-bar"
					/>
				),
			}
		) }
	</h2>
);

const Summary = (): JSX.Element => {
	const {
		areResultsUnique,
		conversionRate,
		conversions,
		ecommerce,
		uniquePageViews,
		totalPageViews,
		revenue,
	} = useAttributes();

	return (
		<ul className="nab-evolution-section__page-views-and-conversions">
			<li>
				<span className="nab-evolution-section__label">
					{ areResultsUnique
						? _x( 'Total Page Views:', 'text', 'nelio-ab-testing' )
						: _x( 'Page Views:', 'text', 'nelio-ab-testing' ) }
				</span>
				<span className="nab-evolution-section__value">
					{ getNumberLabel( totalPageViews ) }
				</span>
			</li>
			{ areResultsUnique && (
				<li>
					<span className="nab-evolution-section__label">
						{ _x(
							'Unique Page Views:',
							'text',
							'nelio-ab-testing'
						) }
					</span>
					<span className="nab-evolution-section__value">
						{ getNumberLabel( uniquePageViews ) }
					</span>
				</li>
			) }
			{ !! ecommerce && (
				<li>
					<span className="nab-evolution-section__label">
						{ _x( 'Revenue:', 'text', 'nelio-ab-testing' ) }
					</span>
					<span className="nab-evolution-section__value">
						{ getMoneyLabel( revenue, ecommerce ) }
					</span>
				</li>
			) }
			<li>
				<span className="nab-evolution-section__label">
					{ areResultsUnique
						? _x(
								'Unique Conversions:',
								'text',
								'nelio-ab-testing'
						  )
						: _x( 'Conversions:', 'text', 'nelio-ab-testing' ) }
				</span>
				<span className="nab-evolution-section__value">
					{ getNumberLabel( conversions ) }
				</span>
				<span className="nab-evolution-section__conversion-rate">
					{ getConversionRateLabel( conversionRate ) }
				</span>
			</li>
		</ul>
	);
};

const ChartSelector = ( {
	value,
	onChange,
}: {
	value: ChartType;
	onChange: ( v: ChartType ) => void;
} ) => {
	const { ecommerce } = useAttributes();

	return (
		<ToggleGroupControl
			className="nab-evolution-section__timeline-selector"
			label=""
			value={ value }
			onChange={ ( newValue ) => onChange( newValue as ChartType ) }
		>
			<ToggleGroupControlOption
				value="conversion-rate"
				label={ _x( 'Conversion Rates', 'text', 'nelio-ab-testing' ) }
			/>

			<ToggleGroupControlOption
				value="views-and-conversions"
				label={ _x(
					'Views and Conversions',
					'text',
					'nelio-ab-testing'
				) }
			/>

			{ !! ecommerce && (
				<>
					<ToggleGroupControlOption
						value="revenue"
						label={ _x( 'Revenue', 'text', 'nelio-ab-testing' ) }
					/>

					<ToggleGroupControlOption
						value="arpc"
						label={ _x( 'ARPC', 'text', 'nelio-ab-testing' ) }
						showTooltip={ true }
					/>
				</>
			) }
		</ToggleGroupControl>
	);
};

type ChartFunction = ( props: { type: ChartType } ) => JSX.Element | null;
const TimelineChart: ChartFunction = ( { type } ) => {
	const { activeGoal, alternatives, areResultsUnique, ecommerce } =
		useAttributes();

	switch ( type ) {
		case 'conversion-rate':
			return (
				<div className="nab-evolution-section__timeline-graphic">
					<ConversionRatesTimelineChart
						alternatives={ alternatives }
						goal={ activeGoal }
						unique={ areResultsUnique }
					/>
				</div>
			);

		case 'views-and-conversions':
			return (
				<div className="nab-evolution-section__timeline-graphic">
					<ViewsAndConversionsTimelineChart
						alternatives={ alternatives }
						goal={ activeGoal }
						unique={ areResultsUnique }
					/>
				</div>
			);

		case 'revenue':
			if ( ! ecommerce ) {
				return null;
			}
			return (
				<div className="nab-evolution-section__timeline-graphic">
					<RevenueTimelineChart
						alternatives={ alternatives }
						goal={ activeGoal }
						unique={ areResultsUnique }
					/>
				</div>
			);

		case 'arpc':
			if ( ! ecommerce ) {
				return null;
			}
			return (
				<div className="nab-evolution-section__timeline-graphic">
					<ArpcTimelineChart
						alternatives={ alternatives }
						goal={ activeGoal }
						unique={ areResultsUnique }
					/>
				</div>
			);
	}
};

const ExtraCharts: ChartFunction = ( { type } ) => (
	<div className="nab-evolution-section__comparison-and-improvement-graphics">
		<div className="nab-evolution-section__comparison-graphic">
			<ComparisonChart type={ type } />
		</div>
		<div className="nab-evolution-section__improvement-graphic">
			<ImprovementChart type={ type } />
		</div>
	</div>
);

const ComparisonChart: ChartFunction = ( { type } ) => {
	const {
		activeGoal,
		alternatives,
		areResultsUnique,
		ecommerce,
		minConfidence,
		winners,
	} = useAttributes();

	switch ( type ) {
		case 'conversion-rate':
		case 'views-and-conversions':
			return (
				<ConversionRatesChart
					alternatives={ alternatives }
					goal={ activeGoal }
					winners={ winners }
					minConfidence={ minConfidence }
					unique={ areResultsUnique }
				/>
			);

		case 'revenue':
			if ( ! ecommerce ) {
				return null;
			}
			return (
				<RevenueChart
					alternatives={ alternatives }
					goal={ activeGoal }
					unique={ areResultsUnique }
				/>
			);

		case 'arpc':
			if ( ! ecommerce ) {
				return null;
			}
			return (
				<ArpcChart
					alternatives={ alternatives }
					goal={ activeGoal }
					unique={ areResultsUnique }
				/>
			);
	}
};

const ImprovementChart: ChartFunction = ( { type } ) => {
	const { activeGoal, alternatives, areResultsUnique, ecommerce } =
		useAttributes();

	switch ( type ) {
		case 'conversion-rate':
		case 'views-and-conversions':
			return (
				<ConversionImprovementChart
					alternatives={ alternatives }
					goal={ activeGoal }
					unique={ areResultsUnique }
				/>
			);

		case 'revenue':
			if ( ! ecommerce ) {
				return null;
			}
			return (
				<RevenueImprovementChart
					alternatives={ alternatives }
					goal={ activeGoal }
					unique={ areResultsUnique }
				/>
			);

		case 'arpc':
			if ( ! ecommerce ) {
				return null;
			}
			return (
				<ArpcImprovementChart
					alternatives={ alternatives }
					goal={ activeGoal }
					unique={ areResultsUnique }
				/>
			);
	}
};

// =====
// HOOKS
// =====

const useAttributes = () => {
	const [ areResultsUnique ] = useAreUniqueResultsVisible();
	return useSelect(
		( select ) => {
			const {
				getAlternativeResultsInExperiment,
				getConversions,
				getExperimentAttribute,
				getPageAttribute,
				getPageViews,
				getTotalPageViews,
				getUniquePageViews,
				getPluginSetting,
				getTotalRevenue,
				getWinnersInExperiment,
				getECommercePlugin,
			} = select( NAB_DATA );

			const activeExperiment =
				getPageAttribute( 'editor/activeExperiment' ) ?? 0;
			const goals =
				getExperimentAttribute( activeExperiment, 'goals' ) ?? [];
			const activeGoalId =
				getPageAttribute( 'editor/activeGoal' ) ?? goals[ 0 ]?.id ?? '';
			const pageViews = getPageViews( activeExperiment );
			const conversions = getConversions(
				activeExperiment,
				activeGoalId
			);
			const revenue = getTotalRevenue( activeExperiment, activeGoalId );

			return {
				totalPageViews: getTotalPageViews( activeExperiment ),
				uniquePageViews: getUniquePageViews( activeExperiment ),
				conversions,
				conversionRate: ( conversions / pageViews ) * 100 || 0,
				activeGoal: activeGoalId,
				areResultsUnique,
				revenue,
				ecommerce: getECommercePlugin( activeExperiment, activeGoalId ),
				alternatives:
					getAlternativeResultsInExperiment( activeExperiment ),
				winners:
					getWinnersInExperiment( activeExperiment ) ?? EMPTY_OBJECT,
				minConfidence: getPluginSetting( 'minConfidence' ),
			};
		},
		[ areResultsUnique ]
	);
};

// =======
// HELPERS
// =======

function getConversionRateLabel( conversionRate?: number ): JSX.Element {
	if ( ! conversionRate ) {
		return <></>;
	}

	return <>({ numberFormat( conversionRate ) }%)</>;
}
