import { useState, useEffect, useCallback, useMemo, useRef } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import { __ } from '@wordpress/i18n';
import { DEFAULTS } from '../utils/field-defs';

export function useSettings() {
	const [ settings, setSettings ] = useState( DEFAULTS );
	const [ initial, setInitial ] = useState( DEFAULTS );
	const [ isLoading, setLoading ] = useState( true );
	const [ isSaving, setSaving ] = useState( false );
	const [ isResetting, setIsResetting ] = useState( false );
	const [ notice, setNotice ] = useState( null );
	const noticeTimer = useRef( null );

	useEffect( () => {
		let cancelled = false;
		apiFetch( { path: '/wuppi/v1/settings' } )
			.then( ( res ) => {
				if ( cancelled ) {
					return;
				}
				const merged = { ...DEFAULTS, ...( res?.settings || {} ) };
				setSettings( merged );
				setInitial( merged );
			} )
			.catch( ( err ) => {
				if ( cancelled ) {
					return;
				}
				setNotice( {
					type: 'error',
					message: err?.message || __( 'Failed to load settings.', 'wuppi' ),
				} );
			} )
			.finally( () => {
				if ( ! cancelled ) {
					setLoading( false );
				}
			} );
		return () => {
			cancelled = true;
		};
	}, [] );

	useEffect( () => () => clearTimeout( noticeTimer.current ), [] );

	const isDirty = useMemo( () => {
		return Object.keys( settings ).some( ( key ) => settings[ key ] !== initial[ key ] );
	}, [ settings, initial ] );

	const updateField = useCallback( ( key, value ) => {
		setSettings( ( prev ) => ( { ...prev, [ key ]: value } ) );
	}, [] );

	const save = useCallback( async () => {
		setSaving( true );
		setNotice( null );
		try {
			const res = await apiFetch( {
				path: '/wuppi/v1/settings',
				method: 'POST',
				data: { settings },
			} );
			const next = { ...DEFAULTS, ...( res?.settings || {} ) };
			setSettings( next );
			setInitial( next );
			setIsResetting( false );
			setNotice( {
				type: 'success',
				message: isResetting
					? __( 'Settings reset to defaults.', 'wuppi' )
					: __( 'Settings saved.', 'wuppi' ),
			} );
			clearTimeout( noticeTimer.current );
			noticeTimer.current = setTimeout( () => setNotice( null ), 3000 );
		} catch ( err ) {
			setIsResetting( false );
			setNotice( {
				type: 'error',
				message: err?.message || __( 'Failed to save settings.', 'wuppi' ),
			} );
		} finally {
			setSaving( false );
		}
	}, [ settings, isResetting ] );

	const discard = useCallback( () => {
		setSettings( initial );
		setNotice( null );
		setIsResetting( false );
	}, [ initial ] );

	const resetToDefaults = useCallback( () => {
		setSettings( DEFAULTS );
		setIsResetting( true );
	}, [] );

	return {
		settings,
		updateField,
		isLoading,
		isSaving,
		isDirty,
		isResetting,
		save,
		discard,
		resetToDefaults,
		notice,
		dismissNotice: () => setNotice( null ),
	};
}
