import { useEffect, useMemo, useState } from '@wordpress/element';
import { useSelect, useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import {
	Store,
	Tags,
	MapPin,
	Award,
	Inbox,
	Database,
	Boxes,
} from 'lucide-react';
import { STORE_KEY } from '../store';
import registry from '../registry';
import BrandLogo from './BrandLogo';
import RecordsView from './RecordsView';

const iconForProvider = ( id = '' ) => {
	const key = String( id ).toLowerCase();
	if ( key.includes( 'store' ) ) return Store;
	if ( key.includes( 'categor' ) ) return Tags;
	if ( key.includes( 'marker' ) ) return MapPin;
	if ( key.includes( 'brand' ) ) return Award;
	if ( key.includes( 'lead' ) ) return Inbox;
	if ( key.includes( 'field' ) ) return Boxes;
	return Database;
};

// UI Core contains no product screens of its own. Host screens
// register through window.cliqUI before the app mounts.
const BUILTIN_SCREENS = {};

// Merge built-ins with host-registered screens ({ id, label, icon, Component }).
const mergeScreens = () => {
	const merged = { ...BUILTIN_SCREENS };
	Object.values( registry.screens() ).forEach( ( s ) => {
		merged[ s.id ] = { label: s.label, Icon: s.icon || s.Icon, Component: s.Component };
	} );
	return merged;
};

const App = () => {
	const { providers, selectedProviderId } = useSelect( ( select ) => {
		const store = select( STORE_KEY );
		return {
			providers: store.getProviders(),
			selectedProviderId: store.getSelectedProviderId(),
		};
	}, [] );

	const { selectProvider } = useDispatch( STORE_KEY );

	// Built-in + host-registered screens, resolved once (host bundle has already
	// registered by the time the app mounts).
	const SCREENS = useMemo( () => mergeScreens(), [] );

	const enabledScreens = useMemo( () => {
		const list =
			( typeof window !== 'undefined' && window.CLIQTHEMES_UI?.app?.screens ) || [];
		return list.filter( ( id ) => SCREENS[ id ] );
	}, [ SCREENS ] );

	const hasDashboard = enabledScreens.includes( 'dashboard' );
	const trailingScreens = enabledScreens.filter( ( id ) => id !== 'dashboard' );

	// `active` is either a screen id (screen:<id>) or a provider id.
	const [ active, setActive ] = useState( null );

	// Restore the active tab from the URL hash (#/<id>[/<subtab>]) on first load,
	// so a refresh stays on the same screen instead of resetting to the dashboard.
	useEffect( () => {
		if ( active ) {
			return;
		}
		const id = ( window.location.hash || '' ).replace( /^#\/?/, '' ).split( '/' )[ 0 ];
		if ( id && enabledScreens.includes( id ) ) {
			setActive( `screen:${ id }` );
			return;
		}
		const prov = providers.find( ( p ) => p.id === id );
		if ( prov ) {
			setActive( prov.id );
			selectProvider( prov.id );
			return;
		}
		if ( hasDashboard ) {
			setActive( 'screen:dashboard' );
		} else if ( providers.length > 0 ) {
			setActive( providers[ 0 ].id );
		}
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [ active, hasDashboard, providers, enabledScreens ] );

	// Reflect the active tab into the URL hash. Only rewrite the FIRST segment so a
	// screen's own sub-tab (e.g. #/builder/<id>) isn't clobbered while you stay
	// on it; switching main tabs resets the sub-tab.
	useEffect( () => {
		if ( ! active ) {
			return;
		}
		const mainId = active.replace( 'screen:', '' );
		const currentMain = ( window.location.hash || '' ).replace( /^#\/?/, '' ).split( '/' )[ 0 ];
		if ( currentMain !== mainId ) {
			window.location.hash = `/${ mainId }`;
		}
	}, [ active ] );

	const selectProviderTab = ( id ) => {
		setActive( id );
		selectProvider( id );
	};

	// React to hash changes AFTER load too (deep links, banner "Support" link),
	// not just on first mount — so `location.hash = '/dashboard'` switches tabs.
	useEffect( () => {
		const onHash = () => {
			const id = ( window.location.hash || '' ).replace( /^#\/?/, '' ).split( '/' )[ 0 ];
			if ( id && enabledScreens.includes( id ) ) {
				setActive( `screen:${ id }` );
				return;
			}
			const prov = providers.find( ( p ) => p.id === id );
			if ( prov ) {
				setActive( prov.id );
				selectProvider( prov.id );
			}
		};
		window.addEventListener( 'hashchange', onHash );
		return () => window.removeEventListener( 'hashchange', onHash );
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [ enabledScreens, providers ] );

	const renderNavItem = ( { id, label, Icon, isActive, onClick } ) => (
		<button
			type="button"
			key={ id }
			className={ `cliqthemes-ui-nav__item${ isActive ? ' is-active' : '' }` }
			onClick={ onClick }
			aria-current={ isActive ? 'page' : undefined }
		>
			<Icon size={ 16 } strokeWidth={ 1.9 } />
			<span>{ label }</span>
		</button>
	);

	const activeScreenId = active && active.startsWith( 'screen:' )
		? active.slice( 7 )
		: null;
	const ActiveScreen = activeScreenId ? SCREENS[ activeScreenId ]?.Component : null;

	const appCfg = ( typeof window !== 'undefined' && window.CLIQTHEMES_UI?.app ) || {};
	const appName = appCfg.name || __( 'Admin', 'cliq-store-locator' );
	const poweredBy = appCfg.poweredBy || 'CliqThemes';
	const BannerBrand = registry.bannerBrand();

	return (
		<div className="cliqthemes-ui-app">
			<header className="cliqthemes-ui-banner">
				<div className="cliqthemes-ui-banner__brand">
					{ BannerBrand ? <BannerBrand /> : (
						<>
							<BrandLogo size={ 40 } className="cliqthemes-ui-banner__logo" />
							<div className="cliqthemes-ui-banner__text">
								<span className="cliqthemes-ui-banner__title">{ appName }</span>
								<span className="cliqthemes-ui-banner__by">{ __( 'by', 'cliq-store-locator' ) } { poweredBy }</span>
							</div>
						</>
					) }
				</div>
				<div className="cliqthemes-ui-banner__toolbar">
					{ registry.toolbarItems().map( ( { id, Component } ) => (
						<Component key={ id || Math.random() } />
					) ) }
				</div>
				{ ( () => {
					// Decorative banner art is host-supplied (domain branding); cliq-ui
					// ships none. Renders nothing if the host registered no motif.
					const Art = registry.bannerArt();
					return Art ? <Art /> : null;
				} )() }
			</header>
			<nav className="cliqthemes-ui-nav" aria-label={ __( 'Sections', 'cliq-store-locator' ) }>
				{ hasDashboard &&
					renderNavItem( {
						id: 'screen:dashboard',
						label: SCREENS.dashboard.label,
						Icon: SCREENS.dashboard.Icon,
						isActive: active === 'screen:dashboard',
						onClick: () => setActive( 'screen:dashboard' ),
					} ) }

				{ providers.map( ( provider ) =>
					renderNavItem( {
						id: provider.id,
						label: provider.label || provider.id,
						Icon: iconForProvider( provider.id ),
						isActive: active === provider.id,
						onClick: () => selectProviderTab( provider.id ),
					} )
				) }

				{ trailingScreens.map( ( id ) =>
					renderNavItem( {
						id: `screen:${ id }`,
						label: SCREENS[ id ].label,
						Icon: SCREENS[ id ].Icon,
						isActive: active === `screen:${ id }`,
						onClick: () => setActive( `screen:${ id }` ),
					} )
				) }
			</nav>

			{ ActiveScreen ? (
				<ActiveScreen />
			) : (
				<RecordsView providerId={ active || selectedProviderId } />
			) }
		</div>
	);
};

export default App;
