/**
 * The app's one global store: connection state, cached Brevo data, settings
 * and the toast queue. Context rather than @wordpress/data — the shared
 * surface is small and every consumer is inside this tree.
 */

import {
	createContext,
	useCallback,
	useContext,
	useMemo,
	useRef,
	useState,
} from '@wordpress/element';
import { getBootstrap } from '../../common';
import { fetchAttributes, fetchLists } from '../api/brevo';
import { fetchSettings } from '../api/settings';

const AppContext = createContext( null );

export function AppProvider( { children } ) {
	const bootstrap = useMemo( () => getBootstrap(), [] );

	const [ connection, setConnection ] = useState( bootstrap.connection );
	const [ settings, setSettings ] = useState( bootstrap.settings || {} );
	const [ brevo, setBrevo ] = useState( {
		lists: [],
		attributes: [],
		cached: false,
		cachedAt: '',
	} );
	const [ brevoState, setBrevoState ] = useState( 'idle' );
	const [ toasts, setToasts ] = useState( [] );

	const toastId = useRef( 0 );

	const dismissToast = useCallback( ( id ) => {
		setToasts( ( current ) =>
			current.filter( ( toast ) => toast.id !== id )
		);
	}, [] );

	const addToast = useCallback( ( message, status = 'success' ) => {
		toastId.current += 1;
		const id = toastId.current;

		setToasts( ( current ) => [ ...current, { id, message, status } ] );

		return id;
	}, [] );

	/**
	 * Load the cached Brevo lists and attributes. Safe to call on mount:
	 * both endpoints read the server-side cache and never hit the API.
	 */
	const loadBrevo = useCallback( async () => {
		setBrevoState( 'loading' );

		try {
			const [ lists, attributes ] = await Promise.all( [
				fetchLists(),
				fetchAttributes(),
			] );

			setBrevo( {
				lists: lists.items || [],
				attributes: attributes.items || [],
				cached: Boolean( lists.cached && attributes.cached ),
				cachedAt: lists.cached_at || '',
			} );
			setBrevoState( 'ready' );
		} catch ( error ) {
			setBrevoState( 'error' );
			addToast( error.message, 'error' );
		}
	}, [ addToast ] );

	const reloadSettings = useCallback( async () => {
		const fresh = await fetchSettings();

		setSettings( fresh );
		setConnection( ( current ) => ( {
			...current,
			hasKey: Boolean( fresh.has_key ),
			hint: fresh.key_hint || '',
			source: fresh.key_source || 'db',
		} ) );

		return fresh;
	}, [] );

	const value = useMemo(
		() => ( {
			bootstrap,
			connection,
			setConnection,
			settings,
			setSettings,
			reloadSettings,
			brevo,
			setBrevo,
			brevoState,
			loadBrevo,
			toasts,
			addToast,
			dismissToast,
		} ),
		[
			bootstrap,
			connection,
			settings,
			reloadSettings,
			brevo,
			brevoState,
			loadBrevo,
			toasts,
			addToast,
			dismissToast,
		]
	);

	return (
		<AppContext.Provider value={ value }>{ children }</AppContext.Provider>
	);
}

export function useApp() {
	const context = useContext( AppContext );

	if ( ! context ) {
		throw new Error( 'useApp must be used inside <AppProvider>' );
	}

	return context;
}
