/**
 * PersonalizeWP Product Collection - Edit Component
 *
 * @package PersonalizeWP
 */

import { __ } from '@wordpress/i18n';
import {
	useBlockProps,
	InspectorControls,
	BlockControls,
	RichText,
} from '@wordpress/block-editor';
import {
	PanelBody,
	SelectControl,
	RangeControl,
	TextControl,
	ToolbarGroup,
	ToolbarDropdownMenu,
	ToolbarButton,
	ButtonGroup,
	Button,
} from '@wordpress/components';
import { useEffect, useMemo, useCallback, useReducer } from '@wordpress/element';
import { store, seen, starFilled, grid, list } from '@wordpress/icons';
import apiFetch from '@wordpress/api-fetch';

import CollectionPicker from './components/CollectionPicker';

const RECIPE_OPTIONS = [
	{
		title: __('Previously Viewed Products', 'personalizewp'),
		value: 'previously-viewed',
		icon: seen,
		info: __('Display products that the current visitor has recently browsed on your store.', 'personalizewp'),
	},
	{
		title: __('Products For You', 'personalizewp'),
		value: 'products-for-you',
		icon: starFilled,
		info: __('Show personalized product recommendations based on visitor segments, categories, and related products.', 'personalizewp'),
	},
];

const FALLBACK_OPTIONS = [
	{
		label: __('Show all products', 'personalizewp'),
		value: 'show_all',
	},
	{
		label: __('Hide block', 'personalizewp'),
		value: 'hide_block',
	},
	{
		label: __('Show custom message', 'personalizewp'),
		value: 'show_message',
	},
];

const MOCK_PRODUCTS = [
	{
		id: 1,
		name: 'Sample Product',
		price_html: '$19.99',
		image_url: '/wp-content/uploads/woocommerce-placeholder-300x300.png',
		type: 'simple',
		average_rating: 4.5,
		permalink: '#'
	},
	{
		id: 2,
		name: 'Variable Product',
		price_html: '$20.00',
		image_url: '/wp-content/uploads/woocommerce-placeholder-300x300.png',
		type: 'variable',
		average_rating: 4.0,
		permalink: '#'
	},
	{
		id: 3,
		name: 'External Product',
		price_html: '$15.00',
		image_url: '/wp-content/uploads/woocommerce-placeholder-300x300.png',
		type: 'external',
		button_text: 'Buy on external store!',
		average_rating: 5.0,
		external_url: '#',
		permalink: '#'
	}
];

const productStateReducer = (state, action) => {
	switch (action.type) {
		case 'SET_LOADING':
			return { ...state, isLoading: action.payload };
		case 'SET_PRODUCTS':
			return { ...state, products: action.payload, isLoading: false, error: null };
		case 'SET_ERROR':
			return { ...state, error: action.payload, isLoading: false };
		case 'RESET':
			return { products: [], isLoading: false, error: null };
		default:
			return state;
	}
};

function useProductButtonConfig(product) {
	return useMemo(() => {
		let text = __('Add to cart', 'personalizewp');
		let className = 'add_to_cart_button ajax_add_to_cart';
		let typeClass = 'product-type-simple';
		let isExternal = false;

		if (product.type === 'external') {
			text = product.button_text || __('Buy product', 'personalizewp');
			className = 'product_type_external';
			typeClass = 'product-type-external';
			isExternal = true;
		} else if (product.type === 'variable') {
			text = __('Select options', 'personalizewp');
			className = 'product_type_variable';
			typeClass = 'product-type-variable';
		}

		return { text, className, typeClass, isExternal };
	}, [product.type, product.button_text]);
}

function useProductClasses(product, buttonConfig, layoutType, index, totalProducts) {
	return useMemo(() => [
		'wc-block-product',
		`post-${product.id}`,
		'product',
		'type-product',
		'status-publish',
		product.image_url ? 'has-post-thumbnail' : '',
		'instock',
		'shipping-taxable',
		'purchasable',
		buttonConfig.typeClass,
		layoutType === 'list' ? 'pwp-list-item' : '',
		index === 0 ? 'first' : '',
		index === totalProducts - 1 ? 'last' : ''
	].filter(Boolean).join(' '), [product, buttonConfig.typeClass, layoutType, index, totalProducts]);
}

const ProductCard = ({ product, layoutType, index, totalProducts, onButtonClick }) => {
	const buttonConfig = useProductButtonConfig(product);
	const isOnSale = product.price_html && product.price_html.includes('<del');
	const productClasses = useProductClasses(product, buttonConfig, layoutType, index, totalProducts);
	const productImage = product.image_url || '/wp-content/uploads/woocommerce-placeholder-300x300.png';

	return (
		<li className={productClasses}>
			<div className="wc-block-components-product-image wc-block-grid__product-image wp-block-woocommerce-product-image">
				<a href="#" onClick={onButtonClick}>
					{isOnSale && (
						<div className="wc-block-components-product-sale-badge wc-block-components-product-sale-badge--align-right wc-block-grid__product-onsale">
							<span aria-hidden="true">{__('Sale', 'personalizewp')}</span>
							<span className="screen-reader-text">{__('Product on sale', 'personalizewp')}</span>
						</div>
					)}
					<img
						decoding="async"
						width="300"
						height="300"
						src={productImage}
						alt={product.name}
						className="attachment-woocommerce_thumbnail size-woocommerce_thumbnail"
						style={{ maxWidth: 'none', objectFit: 'cover' }}
					/>
				</a>
			</div>
			<h3
				style={{ marginBottom: '0.75rem', marginTop: 0 }}
				className="has-text-align-center wp-block-post-title has-medium-font-size"
			>
				<a href="#" onClick={onButtonClick} target="_self">
					{product.name}
				</a>
			</h3>

			{product.average_rating > 0 && (
				<div className="wc-block-components-product-rating">
					<div className="wc-block-components-product-rating__stars" aria-label={`${product.average_rating} out of 5 stars`}>
						{'★'.repeat(Math.floor(product.average_rating))}{'☆'.repeat(5 - Math.floor(product.average_rating))}
					</div>
				</div>
			)}

			<div className="wp-block-woocommerce-product-price">
				<div className="wc-block-components-product-price wc-block-grid__product-price has-text-align-center has-font-size has-small-font-size">
					<span dangerouslySetInnerHTML={{ __html: product.price_html }} />
				</div>
			</div>

			<div className="wp-block-button wc-block-components-product-button align-center wp-block-woocommerce-product-button has-small-font-size">
				{buttonConfig.isExternal ? (
					<a
						href="#"
						className={`wp-block-button__link wp-element-button wc-block-components-product-button__button ${buttonConfig.className} ${buttonConfig.typeClass.replace('-', '_')} has-font-size has-small-font-size has-text-align-center wc-interactive`}
						onClick={onButtonClick}
						rel="nofollow noopener"
						target="_blank"
					>
						<span>{buttonConfig.text}</span>
					</a>
				) : (
					<button
						className={`wp-block-button__link wp-element-button wc-block-components-product-button__button ${buttonConfig.className} ${buttonConfig.typeClass.replace('-', '_')} has-font-size has-small-font-size has-text-align-center wc-interactive`}
						onClick={onButtonClick}
						rel="nofollow"
					>
						<span>{buttonConfig.text}</span>
					</button>
				)}
			</div>
		</li>
	);
};

function LoadingState({ layoutClass }) {
	return (
		<div className={`wp-block-woocommerce-product-collection is-layout-flow wp-block-product-collection-is-layout-flow ${layoutClass}`}>
			<div className="wc-block-components-notices alignwide"></div>
			<div style={{ textAlign: 'center', padding: '2rem', color: '#666' }}>
				<div className="pwp-loading-spinner" style={{
					display: 'inline-block',
					width: '20px',
					height: '20px',
					border: '2px solid #ddd',
					borderTop: '2px solid #874FB9',
					borderRadius: '50%',
					animation: 'spin 1s linear infinite',
					marginRight: '8px'
				}}></div>
				{__('Loading personalized products...', 'personalizewp')}
			</div>
		</div>
	);
}

function ErrorState({ layoutClass }) {
	return (
		<div className={`wp-block-woocommerce-product-collection is-layout-flow wp-block-product-collection-is-layout-flow ${layoutClass}`}>
			<div className="wc-block-components-notices alignwide"></div>
			<div style={{ textAlign: 'center', padding: '2rem', color: '#666' }}>
				<p>{__('Unable to load products. Using fallback display.', 'personalizewp')}</p>
			</div>
		</div>
	);
}

function EmptyState({ layoutClass }) {
	return (
		<div className={`wp-block-woocommerce-product-collection is-layout-flow wp-block-product-collection-is-layout-flow ${layoutClass}`}>
			<div className="wc-block-components-notices alignwide"></div>
			<div style={{ textAlign: 'center', padding: '2rem', color: '#666' }}>
				<p>{__('No products found for this personalization recipe.', 'personalizewp')}</p>
				<p><small>{__('Try viewing some products on your site first.', 'personalizewp')}</small></p>
			</div>
		</div>
	);
}

function ProductGrid({ products, layoutType, gridColumns, onButtonClick }) {
	const layoutClass = layoutType === 'list' ? 'pwp-layout-list' : 'pwp-layout-grid';
	const columnsClass = layoutType === 'grid' ? `columns-${gridColumns}` : 'columns-1';

	return (
		<div className={`wp-block-woocommerce-product-collection is-layout-flow wp-block-product-collection-is-layout-flow ${layoutClass}`}>
			<div className="wc-block-components-notices alignwide"></div>
			<ul className={`${columnsClass} wc-block-product-template__responsive wc-block-product-template wp-block-woocommerce-product-template`}>
				{products.map((product, index) => (
					<ProductCard
						key={product.id}
						product={product}
						layoutType={layoutType}
						index={index}
						totalProducts={products.length}
						onButtonClick={onButtonClick}
					/>
				))}
			</ul>
		</div>
	);
}

export default function edit(props) {
	const { attributes, setAttributes, clientId } = props;

	const {
		queryId,
		query = {},
		displayLayout = { type: 'flex', columns: 3 },
		layoutType = 'grid',
		gridColumns = 3,
		pwpRecipe,
		pwpFallbackBehavior = 'show_all',
		pwpMaxProducts = 8,
		pwpFallbackMessage = '',
		pwpCollectionTitle = '',
	} = attributes;

	const [productState, dispatch] = useReducer(productStateReducer, {
		products: [],
		isLoading: false,
		error: null
	});

	const currentRecipe = useMemo(
		() => RECIPE_OPTIONS.find(option => option.value === pwpRecipe),
		[pwpRecipe]
	);

	const handleButtonClick = useCallback((e) => {
		e.preventDefault();
	}, []);

	const fetchFallbackProducts = useCallback(async () => {
		try {
			apiFetch({
				path: `/wc/store/v1/products?per_page=${pwpMaxProducts || 6}&orderby=date&order=desc`
			}).then( ( latestProducts ) => {
				const fallbackProducts = latestProducts.map(product => ({
					id: product.id,
					name: product.name,
					permalink: product.permalink,
					excerpt: product.short_description || product.description,
					image_url: product.images && product.images.length > 0 ? product.images[0].src : null,
					price_html: product.price_html || `$${product.prices.price}`,
					average_rating: parseFloat(product.average_rating) || 0,
					rating_count: product.rating_count || 0,
					type: product.type || 'simple',
					external_url: product.external_url || '',
					button_text: product.button_text || '',
					sku: product.sku || ''
				}));

				dispatch({ type: 'SET_PRODUCTS', payload: fallbackProducts });
			} );
		} catch (err) {
			dispatch({ type: 'SET_PRODUCTS', payload: [] });
		}
	}, [pwpMaxProducts]);

	const fetchRealProducts = useCallback(async () => {
		if (!pwpRecipe) return;

		dispatch({ type: 'SET_LOADING', payload: true });

		try {
			if (window.PersonalizeWP && window.PersonalizeWP.getVisitorUID) {
				const uid = window.PersonalizeWP.getVisitorUID();

				if (uid) {
					let productIds = [];

					switch (pwpRecipe) {
						case 'previously-viewed':
							const viewActivities = await window.PersonalizeWP.fetchVisitorActivities(uid, {
								activity_type: 'post',
								object_type: 'product'
							});

							productIds = window.PersonalizeWP.getPreviouslyViewedProducts(viewActivities, pwpMaxProducts);
							break;

						case 'products-for-you':
							const allActivities = await window.PersonalizeWP.fetchVisitorActivities(uid);
							const segments = await window.PersonalizeWP.fetchVisitorSegments(uid);
							productIds = window.PersonalizeWP.getRecommendedProducts(allActivities, segments, pwpMaxProducts);
							break;
					}

					if (productIds.length > 0) {
						const productDetails = await window.PersonalizeWP.fetchProductDetails(productIds, pwpRecipe);
						dispatch({ type: 'SET_PRODUCTS', payload: productDetails });
					} else {
						await fetchFallbackProducts();
					}
				} else {
					await fetchFallbackProducts();
				}
			} else {
				await fetchFallbackProducts();
			}
		} catch (err) {
			dispatch({ type: 'SET_ERROR', payload: err.message });
			await fetchFallbackProducts();
		}
	}, [pwpRecipe, pwpMaxProducts, fetchFallbackProducts]);

	const productsForDisplay = useMemo(() => {
		if (productState.isLoading) {
			return [];
		}

		if (productState.error || productState.products.length === 0) {
			return MOCK_PRODUCTS.slice(0, pwpMaxProducts || 6);
		}

		return productState.products.slice(0, pwpMaxProducts || 6);
	}, [productState, pwpMaxProducts]);

	const renderProductGrid = useCallback(() => {
		const layoutClass = layoutType === 'list' ? 'pwp-layout-list' : 'pwp-layout-grid';

		if (productState.isLoading) {
			return <LoadingState layoutClass={layoutClass} />;
		}

		if (productState.error && productsForDisplay.length === 0) {
			return <ErrorState layoutClass={layoutClass} />;
		}

		if (productsForDisplay.length === 0) {
			return <EmptyState layoutClass={layoutClass} />;
		}

		return (
			<ProductGrid
				products={productsForDisplay}
				layoutType={layoutType}
				gridColumns={gridColumns}
				onButtonClick={handleButtonClick}
			/>
		);
	}, [layoutType, productState, productsForDisplay, gridColumns, handleButtonClick]);

	const handleRecipeChange = useCallback((collection) => {
		const selectedRecipe = RECIPE_OPTIONS.find(option => option.value === collection);
		setAttributes({
			pwpRecipe: collection,
			pwpCollectionTitle: selectedRecipe ? selectedRecipe.title : '',
		});
	}, [setAttributes]);

	useEffect(() => {
		if (!queryId) {
			// Generate a simple incremental ID to avoid validation issues
			const blockId = `block-${Date.now()}`;
			setAttributes({ queryId: blockId });
		}
	}, [queryId, setAttributes]);

	useEffect(() => {
		const updatedQuery = {
			...query,
			isProductCollectionBlock: true,
			pwpRecipe: pwpRecipe || 'default',
			pwpMaxProducts: pwpMaxProducts,
			pwpFallbackBehavior: pwpFallbackBehavior,
			pwpFallbackMessage: pwpFallbackMessage,
			lastUpdated: Date.now(),
			perPage: pwpMaxProducts,
			inherit: false,
			postType: 'product',
		};

		const collectionName = pwpRecipe ? `personalizewp-${pwpRecipe}` : 'personalizewp-default';

		setAttributes({
			query: {
				...updatedQuery,
				productCollectionQueryContext: {
					collection: collectionName,
					pwpRecipe: pwpRecipe,
					pwpMaxProducts: pwpMaxProducts,
					pwpFallbackBehavior: pwpFallbackBehavior,
				}
			},
			collection: collectionName
		});
	}, [pwpRecipe, pwpMaxProducts, pwpFallbackBehavior, pwpFallbackMessage, setAttributes]);

	useEffect(() => {
		if (pwpRecipe && !pwpCollectionTitle && currentRecipe) {
			setAttributes({ pwpCollectionTitle: currentRecipe.title });
		}
	}, [pwpRecipe, pwpCollectionTitle, currentRecipe, setAttributes]);

	useEffect(() => {
		if (pwpRecipe) {
			fetchRealProducts();
		}
	}, [pwpRecipe, pwpMaxProducts, fetchRealProducts]);

	const blockProps = useBlockProps({
		className: `wp-block-personalizewp-pro-product-collection pwp-layout-${layoutType} pwp-columns-${gridColumns}`,
		'data-pwp-recipe': pwpRecipe,
		'data-layout-type': layoutType,
		'data-grid-columns': gridColumns,
	});

	if (!pwpRecipe) {
		return (
			<div {...blockProps}>
				<BlockControls>
					<ToolbarGroup>
						<ToolbarDropdownMenu
							icon={store}
							label={__('Choose Collection', 'personalizewp')}
							text={__('Choose Collection', 'personalizewp')}
							controls={RECIPE_OPTIONS.map(option => ({
								title: option.title,
								icon: option.icon,
								onClick: () => handleRecipeChange(option.value),
								isActive: false,
							}))}
						/>
					</ToolbarGroup>
				</BlockControls>

				<CollectionPicker
					currentCollection={null}
					onCollectionChange={handleRecipeChange}
				/>
			</div>
		);
	}

	return (
		<div {...blockProps}>
			<BlockControls>
				<ToolbarGroup>
					<ToolbarDropdownMenu
						icon={currentRecipe?.icon || store}
						label={__('Choose Collection', 'personalizewp')}
						text={currentRecipe?.title || __('Choose Collection', 'personalizewp')}
						controls={RECIPE_OPTIONS.map(option => ({
							title: option.title,
							icon: option.icon,
							onClick: () => handleRecipeChange(option.value),
							isActive: pwpRecipe === option.value,
						}))}
					/>
				</ToolbarGroup>
				<ToolbarGroup>
					<ToolbarButton
						icon={grid}
						label={__('Grid View', 'personalizewp')}
						onClick={() => setAttributes({ layoutType: 'grid' })}
						isActive={layoutType === 'grid'}
					/>
					<ToolbarButton
						icon={list}
						label={__('List View', 'personalizewp')}
						onClick={() => setAttributes({ layoutType: 'list' })}
						isActive={layoutType === 'list'}
					/>
				</ToolbarGroup>
			</BlockControls>

			<InspectorControls>
				<PanelBody title={__('Settings', 'personalizewp')} initialOpen={true}>
					<CollectionPicker
						currentCollection={pwpRecipe}
						onCollectionChange={handleRecipeChange}
					/>

					<SelectControl
						label={__('Fallback Behavior', 'personalizewp')}
						value={pwpFallbackBehavior}
						options={FALLBACK_OPTIONS}
						onChange={(value) => setAttributes({ pwpFallbackBehavior: value })}
						help={__('What to show when personalization data is not available', 'personalizewp')}
						__next40pxDefaultSize={true}
						__nextHasNoMarginBottom={true}
					/>

					{pwpFallbackBehavior === 'show_message' && (
						<TextControl
							label={__('Fallback Message', 'personalizewp')}
							value={pwpFallbackMessage}
							onChange={(value) => setAttributes({ pwpFallbackMessage: value })}
							__next40pxDefaultSize={true}
							__nextHasNoMarginBottom={true}
						/>
					)}

					<RangeControl
						label={__('Max Products', 'personalizewp')}
						value={pwpMaxProducts}
						min={1}
						max={20}
						onChange={(value) => setAttributes({ pwpMaxProducts: value })}
						help={__('Maximum number of products to display', 'personalizewp')}
						__next40pxDefaultSize={true}
						__nextHasNoMarginBottom={true}
					/>

					<div style={{ marginBottom: '16px', marginTop: '24px' }}>
						<label style={{ display: 'block', marginBottom: '8px', fontWeight: '500' }}>
							{__('Layout', 'personalizewp')}
						</label>
						<ButtonGroup>
							<Button
								icon={grid}
								onClick={() => setAttributes({ layoutType: 'grid' })}
								isPressed={layoutType === 'grid'}
								variant={layoutType === 'grid' ? 'primary' : 'secondary'}
							>
								{__('Grid', 'personalizewp')}
							</Button>
							<Button
								icon={list}
								onClick={() => setAttributes({ layoutType: 'list' })}
								isPressed={layoutType === 'list'}
								variant={layoutType === 'list' ? 'primary' : 'secondary'}
							>
								{__('List', 'personalizewp')}
							</Button>
						</ButtonGroup>
					</div>

					{layoutType === 'grid' && (
						<RangeControl
							label={__('Columns', 'personalizewp')}
							value={gridColumns}
							min={1}
							max={6}
							onChange={(value) => {
								setAttributes({
									gridColumns: value,
									displayLayout: {
										...displayLayout,
										columns: value
									}
								});
							}}
							help={__('Number of columns in grid layout', 'personalizewp')}
							__next40pxDefaultSize={true}
							__nextHasNoMarginBottom={true}
						/>
					)}

					{layoutType === 'list' && (
						<div style={{ marginTop: '16px' }}>
							<p style={{ margin: 0, fontSize: '13px', color: '#757575' }}>
								{__('Products will be displayed in a single column list format.', 'personalizewp')}
							</p>
						</div>
					)}
				</PanelBody>
			</InspectorControls>

			{currentRecipe && (
				<div className="pwp-collection-title">
					<RichText
						tagName="h2"
						className="pwp-collection-title__heading"
						value={pwpCollectionTitle}
						onChange={(value) => setAttributes({ pwpCollectionTitle: value })}
						placeholder={currentRecipe.title}
						allowedFormats={['core/bold', 'core/italic']}
					/>
				</div>
			)}

			{renderProductGrid()}


		</div>
	);
}
