/**
 * Main App component.
 *
 * @package Sideconvo
 */

import React from 'react';
import { useState, useEffect } from '@wordpress/element';
import { useAuth } from './contexts/AuthContext';
import SplashScreen from './components/splash/SplashScreen';
import SuccessScreen from './components/splash/SuccessScreen';
import AppLayout from './components/layout/AppLayout';
import AppRoutes from './routes/AppRoutes';

/**
 * Extract widget publish params from the query string.
 * Handles ?publish=true&data-sideconvo-mode=CHAT&data-sideconvo-widget-position=bottom-right&data-sideconvo-message=...
 */
function getPublishParamsFromUrl(): { publish: boolean; mode: string | null; position: string | null; face: string | null; message: string | null } {
	const params = new URLSearchParams( window.location.search );
	return {
		publish:  params.get( 'publish' ) === 'true',
		mode:     params.get( 'data-sideconvo-mode' ),
		position: params.get( 'data-sideconvo-widget-position' ),
		face:     params.get( 'data-sideconvo-face' ),
		message:  params.get( 'data-sideconvo-message' ),
	};
}

/** Strip publish + data-sideconvo-* params from the query string. */
function removePublishParamsFromUrl(): void {
	const params = new URLSearchParams( window.location.search );
	params.delete( 'publish' );
	params.delete( 'data-sideconvo-mode' );
	params.delete( 'data-sideconvo-widget-position' );
	params.delete( 'data-sideconvo-face' );
	params.delete( 'data-sideconvo-message' );
	const newSearch = params.toString();
	window.history.replaceState(
		{},
		'',
		window.location.pathname + ( newSearch ? '?' + newSearch : '' ) + window.location.hash
	);
}

/**
 * Read api_key from either the search query string or the hash fragment.
 * Handles URLs like:
 *   ?page=sideconvo&api_key=KEY
 *   #/settings&api_key=KEY
 */
function getApiKeyFromUrl(): string | null {
	const searchKey = new URLSearchParams( window.location.search ).get( 'api_key' );
	if ( searchKey ) return searchKey;

	// Hash-based: "#/route&api_key=KEY"
	const hash = window.location.hash;
	const ampIdx = hash.indexOf( '&' );
	if ( ampIdx !== -1 ) {
		return new URLSearchParams( hash.slice( ampIdx + 1 ) ).get( 'api_key' );
	}
	return null;
}

/** Strip api_key from both query string and hash fragment. */
function removeApiKeyFromUrl(): void {
	const searchParams = new URLSearchParams( window.location.search );
	searchParams.delete( 'api_key' );

	let cleanHash = window.location.hash;
	const ampIdx = cleanHash.indexOf( '&' );
	if ( ampIdx !== -1 ) {
		const hashParams = new URLSearchParams( cleanHash.slice( ampIdx + 1 ) );
		hashParams.delete( 'api_key' );
		const remaining = hashParams.toString();
		cleanHash = cleanHash.slice( 0, ampIdx ) + ( remaining ? '&' + remaining : '' );
	}

	const newSearch = searchParams.toString();
	window.history.replaceState(
		{},
		'',
		window.location.pathname + ( newSearch ? '?' + newSearch : '' ) + cleanHash
	);
}

/**
 * App component.
 *
 * @return {JSX.Element} App component.
 */
function App() {
	const { isAuthenticated, isLoading, saveApiKey } = useAuth();
	const [showSuccess, setShowSuccess] = useState(false);

	// Capture the key synchronously before it gets stripped from the URL.
	const [pendingApiKey] = useState( () => getApiKeyFromUrl() ?? '' );

	// Capture publish params synchronously before they get stripped from the URL.
	const [pendingPublish] = useState( () => getPublishParamsFromUrl() );

	// Initialise synchronously so we never flash the SplashScreen iframe
	// while an api_key is being validated from the URL.
	const [isProcessingApiKey, setIsProcessingApiKey] = useState(
		() => !! ( pendingApiKey && ! window.sideconvoData?.apiKeyExists )
	);

	// Handle publish=true: enable widget and save any widget config attrs from the URL.
	useEffect(() => {
		if ( ! pendingPublish.publish || ! isAuthenticated ) return;

		removePublishParamsFromUrl();

		const body: Record<string, unknown> = { widget_enabled: true };
		if ( pendingPublish.mode )     body.widget_mode     = pendingPublish.mode;
		if ( pendingPublish.position ) body.widget_position = pendingPublish.position;
		if ( pendingPublish.face )     body.widget_face     = pendingPublish.face;
		if ( pendingPublish.message )  body.widget_message  = pendingPublish.message;

		fetch(
			`${(window as any).sideconvoData.restUrl}sideconvo/v1/widget-settings`,
			{
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
					'X-WP-Nonce': (window as any).sideconvoData.nonce,
				},
				body: JSON.stringify( body ),
			}
		).catch( () => {} );
	}, [isAuthenticated] ); // eslint-disable-line react-hooks/exhaustive-deps

	useEffect(() => {
		if ( ! isProcessingApiKey || ! pendingApiKey ) return;

		// Strip from URL immediately so a reload won't re-trigger this.
		removeApiKeyFromUrl();

		saveApiKey( pendingApiKey ).then( ( result ) => {
			if ( result !== true ) {
				// Validation failed — fall through to SplashScreen.
				setIsProcessingApiKey( false );
			}
			// On success saveApiKey calls window.location.reload(), so we
			// never reach this branch in the success path.
		} );
	}, [] ); // eslint-disable-line react-hooks/exhaustive-deps

	if ( isLoading ) {
		return (
			<div id="sideconvo-app" className="sideconvo-app-skeleton">
				<div className="sideconvo-app-skeleton__sidebar">
					<div className="sideconvo-app-skeleton__logo" />
					<div className="sideconvo-app-skeleton__card" />
					<div className="sideconvo-app-skeleton__section-label" />
					<div className="sideconvo-app-skeleton__nav-item" />
					<div className="sideconvo-app-skeleton__nav-item" />
					<div className="sideconvo-app-skeleton__nav-item" />
					<div className="sideconvo-app-skeleton__nav-item" />
					<div className="sideconvo-app-skeleton__section-label sideconvo-app-skeleton__section-label--spaced" />
					<div className="sideconvo-app-skeleton__nav-item" />
					<div className="sideconvo-app-skeleton__nav-item" />
				</div>
				<div className="sideconvo-app-skeleton__content">
					<div className="sideconvo-app-skeleton__page-header" />
					<div className="sideconvo-app-skeleton__block sideconvo-app-skeleton__block--sm" />
					<div className="sideconvo-app-skeleton__block sideconvo-app-skeleton__block--lg" />
					<div className="sideconvo-app-skeleton__block sideconvo-app-skeleton__block--lg" />
				</div>
			</div>
		);
	}

	// Show success screen after API key is saved
	if (showSuccess && isAuthenticated) {
		return (
			<div id="sideconvo-app">
				<SuccessScreen onContinue={() => setShowSuccess(false)} />
			</div>
		);
	}

	if ( ! isAuthenticated ) {
		return (
			<div id="sideconvo-app">
				<SplashScreen isValidating={ isProcessingApiKey } validatingApiKey={ pendingApiKey } />
			</div>
		);
	}

	// After authentication, show main app with sidebar navigation.
	return (
		<div id="sideconvo-app">
			<AppLayout>
				<AppRoutes />
			</AppLayout>
		</div>
	);
}

export default App;
