import { __ } from '@wordpress/i18n';
import {
	ButtonGroup,
	Button,
	Dropdown,
	NavigableMenu,
} from '@wordpress/components';
import { useBlockEditContext } from '@wordpress/block-editor';
import { useDispatch, useSelect } from '@wordpress/data';
import { applyFilters } from '@wordpress/hooks';
import { Icon, chevronDown } from '@wordpress/icons';
import { useDevice } from '../controls/DeviceContext';

const styleTabs = [
	{ name: 'main', label: __( 'Main', 'axcelersblocks' ) },
	{ name: 'mainHover', label: __( 'Main Hover', 'axcelersblocks' ) },
	{ name: 'link', label: __( 'Link', 'axcelersblocks' ) },
	{ name: 'linkHover', label: __( 'Link Hover', 'axcelersblocks' ) },
	{ name: 'icon', label: __( 'Icon', 'axcelersblocks' ) },
	{ name: 'iconHover', label: __( 'Icon Hover', 'axcelersblocks' ) },
];

/**
 * Keep a short chip row, put the rest in More.
 * When an overflow tab is active, promote it into the last chip slot.
 */
function splitTabs( tabs, activeTab, maxVisibleTabs ) {
	if ( ! Array.isArray( tabs ) || tabs.length <= maxVisibleTabs ) {
		return { visibleTabs: tabs || [], overflowTabs: [] };
	}

	const activeIndex = tabs.findIndex( ( tab ) => tab.name === activeTab );
	const activeInOverflow = activeIndex >= maxVisibleTabs;

	if ( ! activeInOverflow ) {
		return {
			visibleTabs: tabs.slice( 0, maxVisibleTabs ),
			overflowTabs: tabs.slice( maxVisibleTabs ),
		};
	}

	const visibleTabs = [
		...tabs.slice( 0, maxVisibleTabs - 1 ),
		tabs[ activeIndex ],
	];
	const visibleNames = new Set( visibleTabs.map( ( tab ) => tab.name ) );

	return {
		visibleTabs,
		overflowTabs: tabs.filter( ( tab ) => ! visibleNames.has( tab.name ) ),
	};
}

// Use a const function expression (not `export default function`) so terser
// cannot mangle the component binding and `styleTabExtensionControls` to the
// same identifier — that collision throws in strict mode and drops Pro panels.
const StyleTabs = ( {
	uniqueClass,
	activeTab,
	setActiveTab,
	iconSelector = '.icon',
	selectorLabel,
	renderContent,
	tabs = styleTabs,
	tabSelectors = {},
	maxVisibleTabs = 3,
	blockName: blockNameProp,
} ) => {
	const blockEditContext = useBlockEditContext();
	const clientId = blockEditContext?.clientId || '';
	// Allow callers (e.g. addon blocks) to pass an explicit name when context
	// is unavailable or unreliable inside inspector fills.
	const blockName = blockNameProp || blockEditContext?.name || '';
	const deviceContext = useDevice();
	const activeDevice = deviceContext?.activeDevice || 'desktop';

	const attributes = useSelect(
		( select ) => {
			if ( ! clientId ) {
				return {};
			}
			return (
				select( 'core/block-editor' ).getBlockAttributes( clientId ) ||
				{}
			);
		},
		[ clientId ]
	);

	const { updateBlockAttributes } = useDispatch( 'core/block-editor' );

	const setAttributes = ( nextAttributes ) => {
		if (
			! clientId ||
			! nextAttributes ||
			typeof nextAttributes !== 'object'
		) {
			return;
		}
		updateBlockAttributes( clientId, nextAttributes );
	};

	// Build Pro filter context once. Do not store the filter result in a local
	// that terser can mangle into the same identifier as this component — that
	// turns into a self-assignment and throws in strict mode (Pro panels vanish).
	const styleTabFilterContext = {
		blockName,
		clientId,
		attributes,
		setAttributes,
		activeTab,
		activeDevice,
		uniqueClass,
		iconSelector,
	};

	const getSelectorDisplay = () => {
		const baseSelector = selectorLabel || `.${ uniqueClass }`;

		// Block-supplied selectors for custom tabs (e.g. the list's Items / Marker
		// tabs). Each entry is a suffix appended to the base selector.
		if ( tabSelectors[ activeTab ] ) {
			return `${ baseSelector } ${ tabSelectors[ activeTab ] }`;
		}

		switch ( activeTab ) {
			case 'main':
				return baseSelector;
			case 'mainHover':
				return `${ baseSelector }:hover`;
			case 'mainFocus':
				return `${ baseSelector }:focus`;
			case 'mainActive':
				return `${ baseSelector }:active`;
			case 'image':
				return `${ baseSelector } img`;
			case 'link':
				return `${ baseSelector } a`;
			case 'linkHover':
				return `${ baseSelector } a:hover`;
			case 'icon':
				return `${ baseSelector } ${ iconSelector }`;
			case 'iconHover':
				return `${ baseSelector }:hover ${ iconSelector }`;
			case 'svg':
				return `${ baseSelector } ${ iconSelector } svg`;
			case 'linked':
				return `.${ uniqueClass }-link`;
			case 'linkedHover':
				return `.${ uniqueClass }-link:hover`;
			case 'linkedFocus':
				return `.${ uniqueClass }-link:focus`;
			case 'linkedActive':
				return `.${ uniqueClass }-link:active`;
			default:
				return baseSelector;
		}
	};

	const { visibleTabs, overflowTabs } = splitTabs(
		tabs,
		activeTab,
		maxVisibleTabs
	);

	return (
		<div className="axcelersblocks-style-subtabs-wrapper">
			<div className="axcelersblocks-style-uniqueclass-name">
				<code>{ getSelectorDisplay() }</code>
			</div>

			<ButtonGroup className="axcelersblocks-style-tab-buttons">
				{ visibleTabs.map( ( tab ) => (
					<Button
						key={ tab.name }
						isPrimary={ activeTab === tab.name }
						isSecondary={ activeTab !== tab.name }
						onClick={ () => setActiveTab( tab.name ) }
					>
						{ tab.label }
					</Button>
				) ) }

				{ overflowTabs.length > 0 && (
					<Dropdown
						className="axcelersblocks-style-tab-more"
						contentClassName="axcelersblocks-style-tab-more__popover"
						popoverProps={ { placement: 'bottom-start' } }
						renderToggle={ ( { isOpen, onToggle } ) => (
							<Button
								className="axcelersblocks-style-tab-more__toggle"
								isSecondary
								onClick={ onToggle }
								aria-expanded={ isOpen }
								aria-haspopup="listbox"
								aria-label={ __(
									'More style targets',
									'axcelersblocks'
								) }
							>
								<span>
									{ __( 'More', 'axcelersblocks' ) }
									{ overflowTabs.length > 0
										? ` (${ overflowTabs.length })`
										: '' }
								</span>
								<Icon icon={ chevronDown } size={ 16 } />
							</Button>
						) }
						renderContent={ ( { onClose } ) => (
							<NavigableMenu
								className="axcelersblocks-style-tab-more__menu"
								role="listbox"
								aria-label={ __(
									'More style targets',
									'axcelersblocks'
								) }
							>
								{ overflowTabs.map( ( tab ) => (
									<Button
										key={ tab.name }
										role="option"
										className="axcelersblocks-style-tab-more__item"
										variant="tertiary"
										isPressed={ activeTab === tab.name }
										aria-selected={
											activeTab === tab.name
										}
										onClick={ () => {
											setActiveTab( tab.name );
											onClose();
										} }
									>
										{ tab.label }
									</Button>
								) ) }
							</NavigableMenu>
						) }
					/>
				) }
			</ButtonGroup>

			<div className="blockbase-style-controls">
				{ renderContent && renderContent( activeTab ) }
				{ applyFilters(
					'axcelersblocks.styleTabControls',
					null,
					styleTabFilterContext
				) }
			</div>
		</div>
	);
};

export default StyleTabs;
