import { Button } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import apiFetch from '@wordpress/api-fetch';

import {
	defaultFrequencyOptions,
	defaultFrequencyValue,
	defaultDateRangeOptions,
	defaultDateRangeValue,
	getPersonalizationAnalysisData,
	formatString,
} from './utils';

import Analysis from './Analysis';
import AnalysisHeader from './AnalysisHeader';
import AnalysisHeaderContent from './AnalysisHeaderContent';
import AnalysisHeaderActions from './AnalysisHeaderActions';
import AnalysisContent from './AnalysisContent';
import AnalysisGraphAndSummary from './AnalysisGraphAndSummary';
import AnalysisGraph from './AnalysisGraph';
import AnalysisTrend from './AnalysisTrend';
import AnalysisFilters from './AnalysisFilters';
import AnalysisSummary from './AnalysisSummary';
import AnalysisSummaryHeadline from './AnalysisSummaryHeadline';
import AnalysisSummaryRow from './AnalysisSummaryRow';
import NoDataPlaceholder from './NoDataPlaceholder';

const DEFAULT_DATE_RANGE_VALUE = defaultDateRangeValue();
const DATE_RANGE_OPTIONS = Object.entries( defaultDateRangeOptions() ).map(
	( [ key, value ] ) => {
		return {
			label: value,
			value: key,
		};
	}
);

const DEFAULT_FREQUENCY_VALUE = defaultFrequencyValue();
const FREQUENCY_OPTIONS = Object.entries( defaultFrequencyOptions() ).map(
	( [ key, value ] ) => {
		return {
			label: value,
			value: key,
		};
	}
);

function sprintf( format, ...args ) {
	let i = 0;
	return format.replace( /%s/g, () => args[ i++ ] );
}

function PagePersonalizationFilters( props ) {
	const { frequency, setFrequency, dateRange, setDateRange } = props;
	return (
		<>
			{ frequency && (
				<AnalysisFilters title={ __( 'Frequency', 'liana-with-growthstack' ) }>
					{ FREQUENCY_OPTIONS.map( ( option ) => (
						<Button
							key={ option.value }
							isPrimary={ option.value === frequency }
							onClick={ () => setFrequency( option.value ) }
						>
							{ option.label }
						</Button>
					) ) }
				</AnalysisFilters>
			) }
			{ dateRange && (
				<AnalysisFilters title={ __( 'Range', 'liana-with-growthstack' ) }>
					{ DATE_RANGE_OPTIONS.map( ( option ) => (
						<Button
							key={ option.value }
							isPrimary={ option.value === dateRange }
							onClick={ () => setDateRange( option.value ) }
						>
							{ option.label }
						</Button>
					) ) }
				</AnalysisFilters>
			) }
		</>
	);
}

function PersonalizationTableRow( props ) {
	const { variant, frequency, setFrequency, dateRange, setDateRange } = props;

	const [ isExpanded, setIsExpanded ] = useState( false );

	return (
		<>
			<div className="gs-personalization-analytics-table__row">
				<div className="gs-personalization-analytics-table__cell">
					<button
						className="gs-personalization-analytics-table__expander"
						aria-expanded={ isExpanded }
						onClick={ () => setIsExpanded( ! isExpanded ) }
					>
						<div className="gs-personalization-analytics-table__expander-icon">
							<svg
								xmlns="http://www.w3.org/2000/svg"
								width="16"
								height="16"
								fill="currentColor"
								viewBox="0 0 16 16"
							>
								<path
									fillRule="evenodd"
									d="M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708"
								/>
							</svg>
						</div>
						<div className="gs-personalization-analytics-table__expander-content">
							<span className="gs-personalization-analytics-table__variant-name">
								{ variant.name }
							</span>
							{ variant.rules.length > 0 && (
								<div className="gs-personalization-analytics-table__variant-rules">
									{ variant.rules.map( ( rule ) => (
										<span
											key={ rule }
											className="gs-personalization-analytics-table__variant-rule"
										>
											{ rule }
										</span>
									) ) }
								</div>
							) }
						</div>
					</button>
				</div>
				<div className="gs-personalization-analytics-table__cell">
					<AnalysisTrend
						value={
							variant.views.insights.sum.portionOfAllVariants
						}
						notation="percentage"
					/>
				</div>
				<div className="gs-personalization-analytics-table__cell">
					<AnalysisTrend
						value={ variant.views.insights.sum.value }
						notation="compact"
					/>
				</div>
				<div className="gs-personalization-analytics-table__cell">
					<AnalysisTrend
						value={ variant.clicks.insights.sum.value }
						notation="compact"
					/>
				</div>
				<div className="gs-personalization-analytics-table__cell">
					<AnalysisTrend
						value={ variant.clicksPerViews }
						notation="percentage"
					/>
				</div>
			</div>
			{ isExpanded && (
				<div className="gs-personalization-analytics-table__details">
					<Analysis>
						<AnalysisHeader>
							<AnalysisHeaderContent>
								<h2>{ __( 'Views', 'liana-with-growthstack' ) }</h2>
								<p>
									{ __(
										'Tracks all views for this variant.',
										'liana-with-growthstack'
									) }
								</p>
							</AnalysisHeaderContent>
							<AnalysisHeaderActions>
								<PagePersonalizationFilters
									frequency={ frequency }
									setFrequency={ setFrequency }
									dateRange={ dateRange }
									setDateRange={ setDateRange }
								/>
							</AnalysisHeaderActions>
						</AnalysisHeader>
						<AnalysisGraphAndSummary>
							<AnalysisSummary>
								<AnalysisSummaryHeadline
									{ ...variant.views.summaryHeadline }
								/>
								{ variant.views.summaryRows.map( ( row ) => (
									<AnalysisSummaryRow
										key={ row.id }
										{ ...row }
									/>
								) ) }
							</AnalysisSummary>
							<AnalysisGraph
								labels={ variant.views.graphData.map(
									( item ) => item.label
								) }
								data={ [
									{
										label: __( 'Views', 'liana-with-growthstack' ),
										data: variant.views.graphData.map(
											( item ) => item.value
										),
										fill: false,
										backgroundColor: '#007CBB',
										borderColor: '#007CBB',
										lineTension: 0.33,
									},
								] }
							/>
						</AnalysisGraphAndSummary>
					</Analysis>
					<Analysis>
						<AnalysisHeader>
							<AnalysisHeaderContent>
								<h2>{ __( 'Clicks', 'liana-with-growthstack' ) }</h2>
								<p>
									{ __(
										'Tracks clicks for clickable elements inside this variant.',
										'liana-with-growthstack'
									) }
								</p>
							</AnalysisHeaderContent>
							<AnalysisHeaderActions>
								<PagePersonalizationFilters
									frequency={ frequency }
									setFrequency={ setFrequency }
									dateRange={ dateRange }
									setDateRange={ setDateRange }
								/>
							</AnalysisHeaderActions>
						</AnalysisHeader>
						<AnalysisGraphAndSummary>
							<AnalysisSummary>
								<AnalysisSummaryHeadline
									{ ...variant.clicks.summaryHeadline }
								/>
								{ variant.clicks.summaryRows.map( ( row ) => (
									<AnalysisSummaryRow
										key={ row.id }
										{ ...row }
									/>
								) ) }
							</AnalysisSummary>
							<AnalysisGraph
								labels={ variant.clicks.graphData.map(
									( item ) => item.label
								) }
								data={ [
									{
										label: __( 'Clicks', 'liana-with-growthstack' ),
										data: variant.clicks.graphData.map(
											( item ) => item.value
										),
										fill: false,
										backgroundColor: '#007CBB',
										borderColor: '#007CBB',
										lineTension: 0.33,
									},
								] }
							/>
						</AnalysisGraphAndSummary>
					</Analysis>
				</div>
			) }
		</>
	);
}

type PersonalizationVariant = {
	id: string;
	name: string;
	views: PersonalizationAnalyisResult;
	clicks: PersonalizationAnalyisResult;
};

type Personalization = {
	id: string;
	name: string;
	variants: PersonalizationVariant[];
};

export default function PagePersonalization( props ) {
	const {
		getCachedData,
		setCachedData,
		postId,
		editLink,
		focusPersonalizationId = null,
		focusVariantTitlesToOverride = null,
		hasABTests,
	} = props;

	const [ dateRange, setDateRange ] = useState( DEFAULT_DATE_RANGE_VALUE );
	const [ frequency, setFrequency ] = useState( DEFAULT_FREQUENCY_VALUE );

	const [ personalizations, setPersonalizations ] = useState( null );
	const [ hasPersonalizations, setHasPersonalizations ] = useState( false );
	const [ showAdvanced, setShowAdvanced ] = useState( [] ); // needs to be array as there are multiple personalizations

	const [ data, setData ] = useState( null );
	const [ error, setError ] = useState( null );

	const ENDPOINT = `/growthstack/v1/analytics/page/${ postId }/personalization/`;

	useEffect( () => {
		const cached = getCachedData( ENDPOINT );

		if ( cached?.isFetched ) {
			setData( cached.data );
			setError( cached.error );
			return;
		}

		setError( null );

		apiFetch( { path: ENDPOINT } )
			.then( ( response ) => {
				const responseData = response?.data?.data || [];
				setData( responseData );
				setCachedData( ENDPOINT, responseData, null );
			} )
			.catch( ( fetchError ) => {
				setError( fetchError );
				setCachedData( ENDPOINT, null, fetchError );
				// eslint-disable-next-line no-console
				console.error(
					'Failed to fetch page personalization data',
					fetchError
				);
			} );
	}, [ getCachedData, setCachedData, postId, ENDPOINT ] );

	useEffect( () => {
		if ( data ) {
			const _personalizations = [] as Personalization[];

			let rawPersonalizationsData = data || {};

			// In editor, filter out personalizations that are not the focus
			if ( focusPersonalizationId !== null ) {
				const filteredPersonalizations = {};
				Object.entries( rawPersonalizationsData ).forEach(
					( [ personalizationId, rawDataPointsVariants ] ) => {
						if ( personalizationId === focusPersonalizationId ) {
							filteredPersonalizations[ personalizationId ] =
								rawDataPointsVariants;
						}
					}
				);
				rawPersonalizationsData = filteredPersonalizations;
			}

			let personalizationNumber = 1;

			const hasOnlyOnePersonalization =
				Object.keys( rawPersonalizationsData ).length === 1;

			Object.entries( rawPersonalizationsData ).forEach(
				( [ personalizationId, personalizationData ] ) => {
					let personalizationTitle =
						// @ts-ignore
						personalizationData?.title || null;
					const rawDataPointsVariants =
						// @ts-ignore
						personalizationData?.variants || {};
					const variants = Object.entries(
						rawDataPointsVariants as { [ key: string ]: any }
					).map( ( [ variantId, variantData ] ) => {
						let variantTitle = variantData?.title || variantId;
						const rawDataPoints = variantData?.data || {};

						// get raw data points from other variants
						const otherVariantsRawDataPoints: any[] = [];
						Object.entries(
							rawDataPointsVariants as { [ key: string ]: any }
						).forEach( ( [ otherVariantId, otherVariantData ] ) => {
							if ( otherVariantId !== variantId ) {
								otherVariantsRawDataPoints.push(
									otherVariantData?.data || {}
								);
							}
						} );

						const views = getPersonalizationAnalysisData(
							rawDataPoints as PageRawDataPoints,
							otherVariantsRawDataPoints,
							'view_count',
							dateRange,
							frequency
						);
						const clicks = getPersonalizationAnalysisData(
							rawDataPoints as PageRawDataPoints,
							otherVariantsRawDataPoints,
							'click_count',
							dateRange,
							frequency
						);

						let clicksPerViews = 0;
						if (
							views?.insights?.sum?.value &&
							views?.insights?.sum?.value > 0 &&
							clicks?.insights?.sum?.value &&
							clicks?.insights?.sum?.value > 0
						) {
							clicksPerViews =
								( clicks.insights.sum.value /
									views.insights.sum.value ) *
								100;
						}

						if (
							focusVariantTitlesToOverride !== null &&
							focusVariantTitlesToOverride[ variantId ]
						) {
							variantTitle =
								focusVariantTitlesToOverride[ variantId ];
						}
						if ( variantTitle === '' ) {
							variantTitle = variantId;
						}

						let rules = [];

						if ( variantData?.rules ) {
							rules = variantData.rules.map( ( rule ) => {
								return rule.name;
							} );
						}

						return {
							id: variantId,
							name: variantTitle,
							rules,
							views,
							clicks,
							clicksPerViews,
						};
					} );

					if ( variants.length > 0 ) {
						if ( personalizationTitle === null ) {
							personalizationTitle = hasOnlyOnePersonalization
								? __( 'Personalization', 'liana-with-growthstack' )
								: formatString(
										// Translators: %s is the personalization number, e.g. "1"
										__(
											'Personalization %s',
											'liana-with-growthstack'
										),
										personalizationNumber
								  );
						}

						_personalizations.push( {
							id: personalizationId,
							name: personalizationTitle,
							variants: variants as PersonalizationVariant[],
						} );
						personalizationNumber++;
					}
				}
			);

			if ( _personalizations.length > 0 ) {
				setHasPersonalizations( true );
			}
			setPersonalizations( _personalizations );
		}
	}, [
		data,
		dateRange,
		focusPersonalizationId,
		focusVariantTitlesToOverride,
		frequency,
	] );

	const isLoading = ! data && ! error;

	return (
		<div className="gs-personalization-analytics">
			{ isLoading && <div className="gs-box is-skeleton"></div> }
			{ ! isLoading && ! hasPersonalizations && (
				<div className="gs-box">
					{ hasPersonalizations && (
						<h2 className="gs-box__title">
							{ __( 'Personalizations', 'liana-with-growthstack' ) }
						</h2>
					) }
					{ ! hasABTests && (
						<>
							<NoDataPlaceholder type="personalization">
								<p>
									{ __(
										'No personalizations on this page',
										'liana-with-growthstack'
									) }
								</p>
								<p>
									{ __(
										'You can create personalizations for this page to show different content to different visitors.',
										'liana-with-growthstack'
									) }
								</p>
								<Button variant="primary" href={ editLink }>
									{ __(
										'Create Personalization',
										'liana-with-growthstack'
									) }
								</Button>
							</NoDataPlaceholder>
						</>
					) }
					{ hasABTests && (
						<>
							<NoDataPlaceholder type="personalization">
								<p>
									{ __(
										'No personalizations on this page',
										'liana-with-growthstack'
									) }
								</p>
								<p>
									{ __(
										'You can create personalizations for this page to show different content to different visitors.',
										'liana-with-growthstack'
									) }
								</p>
								<p>
									{ __(
										"You can't create personalizations while an A/B test is running on this page.",
										'liana-with-growthstack'
									) }
								</p>
							</NoDataPlaceholder>
						</>
					) }
				</div>
			) }
			{ ! isLoading &&
				hasPersonalizations &&
				personalizations.length > 0 && (
					<>
						{ personalizations.map( ( personalization ) => (
							<>
								<div className="gs-box">
									<Analysis>
										<AnalysisHeader>
											<AnalysisHeaderContent>
												<h2>
													{ personalization.name }
												</h2>
												<p>
													{ formatString(
														// Translators: %s is the personalization ID
														__(
															'ID: %s',
															'liana-with-growthstack'
														),
														personalization.id
													) }
												</p>
											</AnalysisHeaderContent>
											<AnalysisHeaderActions>
												<PagePersonalizationFilters
													dateRange={ dateRange }
													setDateRange={
														setDateRange
													}
												/>
											</AnalysisHeaderActions>
										</AnalysisHeader>
										<AnalysisContent>
											<div className="gs-personalization-analytics-table-wrap">
												<div className="gs-personalization-analytics-table">
													<div className="gs-personalization-analytics-table__header">
														<div className="gs-personalization-analytics-table__cell">
															{ __(
																'Variant',
																'liana-with-growthstack'
															) }
														</div>
														<div className="gs-personalization-analytics-table__cell">
															{ __(
																'Show Rate',
																'liana-with-growthstack'
															) }
														</div>
														<div className="gs-personalization-analytics-table__cell">
															{ __(
																'Views',
																'liana-with-growthstack'
															) }
														</div>
														<div className="gs-personalization-analytics-table__cell">
															{ __(
																'Clicks',
																'liana-with-growthstack'
															) }
														</div>
														<div className="gs-personalization-analytics-table__cell">
															{ __(
																'Clicks / Views',
																'liana-with-growthstack'
															) }
														</div>
													</div>
													{ personalization.variants.map(
														( variant ) => (
															<PersonalizationTableRow
																key={
																	variant.id
																}
																variant={
																	variant
																}
																frequency={
																	frequency
																}
																setFrequency={
																	setFrequency
																}
																dateRange={
																	dateRange
																}
																setDateRange={
																	setDateRange
																}
															/>
														)
													) }
												</div>
											</div>
										</AnalysisContent>
									</Analysis>
									<div className="gs-ab-advanced">
										<Button
											className="gs-ab-advanced__button"
											onClick={ () => {
												const currentShowAdvanced =
													showAdvanced[
														personalization.id
													] !== undefined
														? showAdvanced[
																personalization
																	.id
														  ]
														: false;
												setShowAdvanced( {
													...showAdvanced,
													[ personalization.id ]:
														! currentShowAdvanced,
												} );
											} }
											aria-expanded={
												showAdvanced[
													personalization.id
												] !== undefined
													? showAdvanced[
															personalization.id
													  ]
													: false
											}
										>
											<span>
												{ (
													showAdvanced[
														personalization.id
													] !== undefined
														? showAdvanced[
																personalization
																	.id
														  ]
														: false
												)
													? __(
															'Hide advanced info',
															'liana-with-growthstack'
													  )
													: __(
															'Show advanced info',
															'liana-with-growthstack'
													  ) }
											</span>
											<svg
												xmlns="http://www.w3.org/2000/svg"
												width="16"
												height="16"
												fill="currentColor"
												viewBox="0 0 16 16"
											>
												<path
													fillRule="evenodd"
													d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708"
												/>
											</svg>
										</Button>
										{ showAdvanced[
											personalization.id
										] && (
											<div className="gs-ab-advanced__content">
												<p>
													<strong>
														{ __(
															'Google Analytics',
															'liana-with-growthstack'
														) }
													</strong>
												</p>
												<p
													dangerouslySetInnerHTML={ {
														__html: sprintf(
															// Translators: %s is the data layer event name
															__(
																'You can find this personalization in Google Analytics by the data layer event %s',
																'liana-with-growthstack'
															),
															'<code>growthstack_personalization</code>'
														),
													} }
												></p>
												<p
													dangerouslySetInnerHTML={ {
														__html: sprintf(
															// Translators: %s is the personalization ID
															__(
																'Find visitors that saw any version of this personalization by personalizationId: %s',
																'liana-with-growthstack'
															),
															'<code>' +
																personalization.id +
																'</code>'
														),
													} }
												></p>
												<p>
													{ __(
														'You can focus into different versions by variantId:',
														'liana-with-growthstack'
													) }
												</p>
												<ol>
													{ personalization.variants.map(
														( variant ) => (
															<li
																key={
																	variant.id
																}
															>
																{ variant.name }
																:{ ' ' }
																<code>
																	{
																		variant.id
																	}
																</code>
															</li>
														)
													) }
												</ol>
											</div>
										) }
									</div>
								</div>
							</>
						) ) }
					</>
				) }
		</div>
	);
}
