import React, { useCallback, useMemo } from 'react';
import { useFilters } from '@/hooks/useFilters';
import useGoalsData from '@/hooks/useGoalsData';
import { useInsightsStore } from '@/store/useInsightsStore';
import { useDate } from '@/store/useDateStore';
import HelpTooltip from '@/components/Common/HelpTooltip';
import Icon from '@/utils/Icon';
import { __ } from '@wordpress/i18n';
import { toast } from '@/utils/toast';
import { isValidDate } from '@/utils/formatting';
import useSettingsData from '@/hooks/useSettingsData';

/**
 * ClickToFilter component - makes any child element clickable to apply filters.
 *
 * @param {string}          filter      - The filter type (e.g., 'country_code', 'page_url', 'device').
 * @param {string}          filterValue - The specific value to filter by.
 * @param {string}          label       - Display label for tooltips.
 * @param {React.ReactNode} children    - The wrapped content that becomes clickable.
 * @param {string}          startDate   - Optional start date to set when filtering.
 * @param {string}          endDate     - Optional end date to set when filtering.
 * @param {Object}          row         - Optional end date to set when filtering.
 * @param {boolean}         useContainerForFilter - Make wrapped content clickable for filtering.
 * @param {React.ReactNode} afterChildren - Optional content shown in the hover overlay.
 * @return {React.ReactElement}
 */
// fallow-ignore-next-line complexity
const ClickToFilter = ({
	filter,
	filterValue,
	label,
	children,
	startDate,
	endDate,
	row,
	useContainerForFilter = false,
	afterChildren = null
}) => {

	// Filter actions from TanStack Router-based hook.
	const { setFilters, filtersConf, getActiveFilters } = useFilters();
	const { getGoal } = useGoalsData();
	const setInsightsMetrics = useInsightsStore( ( state ) => state.setMetrics );
	const insightsMetrics = useInsightsStore( ( state ) => state.getMetrics() );
	const setStartDate = useDate( ( state ) => state.setStartDate );
	const setEndDate = useDate( ( state ) => state.setEndDate );
	const setRange = useDate( ( state ) => state.setRange );

	const { getValue } = useSettingsData();
	const filterByDomain = getValue( 'filtering_by_domain' );

	// Check if the filter is allowed
	const isValidFilter = useMemo( () => {
		return (
			filter &&
			filtersConf &&
			Object.prototype.hasOwnProperty.call( filtersConf, filter )
		);
	}, [ filter, filtersConf ]);

	// Check if this filter value represents a URL that can be opened externally
	const isExternalLinkable = useMemo( () => {
		if ( ! filterValue ) {
			return false;
		}

		// Check if it's a URL-related filter type
		const urlFilters = [ 'page_url', 'referrer' ];
		if ( urlFilters.includes( filter ) ) {
			return true;
		}

		// Check if the value looks like a URL
		try {
			const urlPattern = /^https?:\/\/.+/i;
			return urlPattern.test( filterValue );
		} catch {
			return false;
		}
	}, [ filter, filterValue ]);

	// Handle external link clicks
	const handleExternalLinkClick = useCallback(

		// fallow-ignore-next-line complexity
		( e ) => {
			e.stopPropagation();

			let url = filterValue;

			// For page_url filters, construct the full URL if it's a relative path
			if ( 'page_url' === filter && ! filterValue.startsWith( 'http' ) ) {

				// Get the site URL from window.burst_settings if available, otherwise use current origin
				let siteUrl = window.burst_settings?.site_url || window.location.origin;

				// If filterBydomain is active, check if we have the domain in the row dataset. If not, we try the domain filter, if used.
				if ( filterByDomain ) {
					const activeFilters = getActiveFilters();
					const protocol =
						-1 !== siteUrl.indexOf( 'https:' ) ? 'https://' : 'http://';

					if ( Object.prototype.hasOwnProperty.call( row, 'host' ) ) {
						siteUrl = `${protocol}${row.host}`;
					} else if (
						Object.prototype.hasOwnProperty.call( activeFilters, 'host' )
					) {
						const hostValue =
							activeFilters.host?.replace?.( /^!/, '' ) ?? activeFilters.host;
						siteUrl = `${protocol}${hostValue}`;
					}
				}
				url = `${siteUrl}${filterValue.startsWith( '/' ) ? '' : '/'}${filterValue}`;
			}

			if ( 'referrer' === filter && ! filterValue.startsWith( 'http' ) ) {

				//assuming https always.
				url = `https://${filterValue}`;
			}

			window.open( url, '_blank', 'noopener,noreferrer' );
		},
		[ filter, filterValue ] // eslint-disable-line react-hooks/exhaustive-deps
	);

	// Memoize tooltip content for filter icon
	const filterTooltip = useMemo( () => {
		return label ?
			`${__( 'Click to filter by:', 'burst-statistics' )} ${label}` :
			__( 'Click to filter', 'burst-statistics' );
	}, [ label ]);

	// Memoize tooltip content for external link icon
	const externalLinkTooltip = useMemo( () => {
		return __( 'Open in new tab', 'burst-statistics' );
	}, []);

	// Handle date range updates
	// fallow-ignore-next-line complexity
	const handleDateRange = useCallback( () => {
		if ( ! startDate ) {
			return;
		}

		let formattedStartDate = '';
		let formattedEndDate = '';

		// Format start date
		if ( /^\d+$/.test( startDate ) ) {

			// Unix timestamp (10 digits) or Unix in milliseconds (13 digits)
			const unixTime =
				10 === startDate.toString().length ? startDate * 1000 : startDate;
			formattedStartDate = new Date( unixTime ).toISOString().split( 'T' )[0];
		} else if ( /\d{4}-\d{2}-\d{2}/.test( startDate ) ) {

			// Already in yyyy-MM-dd format
			formattedStartDate = startDate;
		}

		// Format end date (default to today if not provided)
		if ( ! endDate ) {
			formattedEndDate = new Date().toISOString().split( 'T' )[0];
		} else if ( /^\d+$/.test( endDate ) ) {
			const unixTime =
				10 === endDate.toString().length ? endDate * 1000 : endDate;
			formattedEndDate = new Date( unixTime ).toISOString().split( 'T' )[0];
		} else if ( /\d{4}-\d{2}-\d{2}/.test( endDate ) ) {
			formattedEndDate = endDate;
		}

		// Apply date range if valid
		if ( isValidDate( formattedStartDate ) && isValidDate( formattedEndDate ) ) {
			setStartDate( formattedStartDate );
			setEndDate( formattedEndDate );
			setRange( 'custom' );
		}
	}, [ startDate, endDate, setStartDate, setEndDate, setRange ]);

	// Handle goal-specific filtering
	const handleGoalFilter = useCallback(
		( goalId ) => {
			const goal = getGoal( goalId );

			if ( goal?.goal_specific_page ) {
				setFilters( 'page_url', goal.goal_specific_page );
				setFilters( 'goal_id', goalId );
				toast.info(
					__( 'Filtering by goal & goal specific page', 'burst-statistics' )
				);
			} else {
				setFilters( 'goal_id', goalId );
				toast.info( __( 'Filtering by goal', 'burst-statistics' ) );
			}

			// Add conversions metric if not already present
			if ( ! insightsMetrics.includes( 'conversions' ) ) {
				setInsightsMetrics([ ...insightsMetrics, 'conversions' ]);
			}
		},
		[ getGoal, setFilters, insightsMetrics, setInsightsMetrics ]
	);

	const applyFilter = useCallback( () => {

		// Validate filter before processing
		if ( ! isValidFilter ) {
			console.warn(
				`ClickToFilter: Invalid filter "${filter}" - not found in filter configuration`
			);
			return;
		}

		// Apply the appropriate filter
		if ( 'goal_id' === filter ) {
			handleGoalFilter( filterValue );
		} else {
			setFilters( filter, filterValue );
		}

		// Apply date range if provided
		handleDateRange();
	}, [
		filter,
		filterValue,
		isValidFilter,
		handleGoalFilter,
		setFilters,
		handleDateRange
	]);

	// Main filter click handler
	const handleFilterClick = useCallback(
		( e ) => {
			e.stopPropagation();
			applyFilter();
		},
		[ applyFilter ]
	);

	const handleContainerKeyDown = useCallback(
		( e ) => {
			if ( 'Enter' === e.key || ' ' === e.key ) {
				e.preventDefault();
				e.stopPropagation();
				applyFilter();
			}
		},
		[ applyFilter ]
	);

	// Early return if no filter configuration or invalid filter
	if ( ! filter || ! filterValue ) {
		return <>{children}</>;
	}

	// If filter is not valid, render children without click functionality
	if ( ! isValidFilter ) {
		if ( 'development' === process.env.NODE_ENV ) {
			console.warn(
				`ClickToFilter: Filter "${filter}" is not configured in FILTER_CONFIG`
			);
		}
		return <>{children}</>;
	}

	return (
		<div className="group relative @md:min-w-36 min-w-0 w-full">
			{/* Main content. */}
			{useContainerForFilter ? (
				<HelpTooltip content={filterTooltip} asChild>
					<div
						className="min-w-0 cursor-pointer"
						onClick={handleFilterClick}
						onKeyDown={handleContainerKeyDown}
						role="button"
						tabIndex={0}
					>
						{children}
					</div>
				</HelpTooltip>
			) : (
				<div className="w-full group-hover:bg-gray-50 p-2 rounded-md">{children}</div>
			)}

			{( afterChildren || ( ! useContainerForFilter || isExternalLinkable ) ) && (
				<div
					className="pointer-events-none absolute right-1 top-1/2 z-10 flex -translate-y-1/2 p-1 items-center gap-1 pl-5 pr-1 opacity-0 transition-opacity duration-150 group-hover:pointer-events-auto group-hover:opacity-100"
					style={{
						background: 'linear-gradient(to right, transparent, var(--color-gray-50) 20px)'
					}}
				>
					{afterChildren}

					{/* Filter icon - show unless container click mode is enabled. */}
					{! useContainerForFilter && (
						<HelpTooltip content={filterTooltip}>
							<div
								onClick={handleFilterClick}
								className="flex items-center justify-center w-6 h-6 bg-gray-100 hover:bg-white border border-gray-200 rounded shadow-sm hover:shadow-md transition-all duration-150 cursor-pointer"
							>
								<Icon name="filter" size={14} color="black" />
							</div>
						</HelpTooltip>
					)}

					{/* External link icon - only show for URLs. */}
					{isExternalLinkable && (
						<HelpTooltip content={externalLinkTooltip}>
							<div
								onClick={handleExternalLinkClick}
								className="flex items-center justify-center w-6 h-6 bg-gray-100 hover:bg-white border border-gray-200 rounded shadow-sm hover:shadow-md transition-all duration-150 cursor-pointer"
							>
								<Icon name="referrers" size={14} color="black" />
							</div>
						</HelpTooltip>
					)}
				</div>
			)}
		</div>
	);
};

export default React.memo( ClickToFilter );
