import { useState, useEffect, useRef, useCallback } from 'react';
import { Button } from '@/components/ui/button';
import { post, getWordPressConfig } from '@/api/client';
import { logError } from '@/errors/logger';

/**
 * AddressAutocompleteInput
 *
 * Predictive address field backed by Google Places (via the plugin proxy →
 * marketgoo backend). As the user types we debounce calls to the autocomplete
 * endpoint and show a predictions dropdown; picking one resolves its canonical
 * details and reports them through `onSelect`.
 *
 * A single `session_token` (UUID) is reused across the autocomplete keystrokes
 * and the details call to group Google billing, then rotated after each
 * selection. If the user types without picking a prediction, only `onChange`
 * fires (free-text fallback — no canonical place object).
 *
 * @param {string} value - Current input value (controlled)
 * @param {Function} onChange - (string) => void, free-text changes (also fired with the formatted address on select)
 * @param {Function} [onSelect] - (place|null) => void, prediction chosen; place = { place_id, name, formatted_address, lat, lng } (null if details lookup failed)
 * @param {Function} [onSend] - () => void, Enter pressed (used by the chat to submit free text)
 * @param {string} [placeholder]
 * @param {boolean} [disabled=false]
 * @param {boolean} [autoFocus=false]
 * @param {boolean} [showSendButton=false] - Render a trailing Send button (chat layout)
 * @param {boolean} [dropUp=false] - Open the predictions dropdown above the input (chat layout, where the field sits at the bottom of an overflow-hidden container)
 * @param {string} [inputClassName] - Override classes for the <input>
 * @param {string} [wrapperClassName] - Extra classes for the positioning wrapper
 */
const DEBOUNCE_MS = 300;
const MIN_CHARS = 3;

const newSessionToken = () =>
	window.crypto?.randomUUID?.() ??
	`sess-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;

const AddressAutocompleteInput = ({
	value,
	onChange,
	onSelect,
	onSend,
	placeholder = 'Start typing your business address…',
	disabled = false,
	autoFocus = false,
	showSendButton = false,
	dropUp = false,
	inputClassName = '',
	wrapperClassName = '',
}) => {
	const { endpoints } = getWordPressConfig();
	const [predictions, setPredictions] = useState([]);
	const [open, setOpen] = useState(false);
	const sessionTokenRef = useRef(newSessionToken());
	const debounceRef = useRef(null);
	const containerRef = useRef(null);
	const inputRef = useRef(null);

	useEffect(() => {
		if (autoFocus && !disabled) inputRef.current?.focus();
	}, [autoFocus, disabled]);

	// Close the dropdown when clicking outside the field.
	useEffect(() => {
		const onClickOutside = (e) => {
			if (
				containerRef.current &&
				!containerRef.current.contains(e.target)
			) {
				setOpen(false);
			}
		};
		document.addEventListener('mousedown', onClickOutside);
		return () =>
			document.removeEventListener('mousedown', onClickOutside);
	}, []);

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

	const fetchPredictions = useCallback(
		async (input) => {
			const trimmed = (input || '').trim();
			if (trimmed.length < MIN_CHARS) {
				setPredictions([]);
				setOpen(false);
				return;
			}
			try {
				const res = await post(endpoints.addressAutocomplete, {
					input: trimmed,
					session_token: sessionTokenRef.current,
				});
				const list = res?.predictions || [];
				setPredictions(list);
				setOpen(list.length > 0);
			} catch (err) {
				logError(err, {
					action: 'address_autocomplete',
					component: 'AddressAutocompleteInput',
				});
				setPredictions([]);
				setOpen(false);
			}
		},
		[endpoints.addressAutocomplete]
	);

	const handleChange = (next) => {
		onChange?.(next);
		clearTimeout(debounceRef.current);
		debounceRef.current = setTimeout(
			() => fetchPredictions(next),
			DEBOUNCE_MS
		);
	};

	const handlePick = async (prediction) => {
		setOpen(false);
		setPredictions([]);
		clearTimeout(debounceRef.current);
		try {
			const raw = await post(endpoints.addressDetails, {
				place_id: prediction.place_id,
				session_token: sessionTokenRef.current,
			});
			// Keep only the contract fields: the plugin proxy / ApiConnector wraps
			// the response with a transport-level `success` flag we don't want
			// ending up inside the persisted location_complete object.
			const place = raw
				? {
						place_id: raw.place_id,
						name: raw.name,
						formatted_address: raw.formatted_address,
						lat: raw.lat,
						lng: raw.lng,
					}
				: null;
			onChange?.(place?.formatted_address || prediction.description);
			onSelect?.(place);
		} catch (err) {
			logError(err, {
				action: 'address_details',
				component: 'AddressAutocompleteInput',
			});
			// Fall back to the prediction text as free text (no canonical place).
			onChange?.(prediction.description);
			onSelect?.(null);
		} finally {
			// Selecting closes the Google billing session; start a fresh one.
			sessionTokenRef.current = newSessionToken();
		}
	};

	const handleKeyDown = (e) => {
		if (e.key === 'Enter' && !e.shiftKey) {
			e.preventDefault();
			setOpen(false);
			onSend?.();
		} else if (e.key === 'Escape') {
			setOpen(false);
		}
	};

	const defaultInputClasses = showSendButton
		? 'flex-1 bg-transparent !border-none !outline-none !text-sm !placeholder:text-muted-foreground'
		: 'w-full rounded-lg border! border-border! bg-neutral-50! px-5! py-3! paragraph-regular text-foreground focus:outline-none focus:ring-2 focus:ring-ring';

	return (
		<div ref={containerRef} className={`relative ${wrapperClassName}`}>
			<div
				className={
					showSendButton
						? 'flex items-center gap-2 px-2 py-2 bg-card border border-border rounded-sm'
						: ''
				}
			>
				<input
					ref={inputRef}
					type="text"
					value={value}
					onChange={(e) => handleChange(e.target.value)}
					onKeyDown={handleKeyDown}
					placeholder={placeholder}
					disabled={disabled}
					autoComplete="off"
					className={inputClassName || defaultInputClasses}
				/>
				{showSendButton && (
					<Button
						onClick={() => onSend?.()}
						disabled={!value?.trim() || disabled}
						variant="secondary"
						size="sm"
					>
						Send
					</Button>
				)}
			</div>

			{open && predictions.length > 0 && (
				<ul
					className={`absolute z-50 left-0 right-0 max-h-60 overflow-auto rounded-sm border border-border bg-card shadow-md ${
						dropUp ? 'bottom-full mb-1' : 'mt-1'
					}`}
				>
					{predictions.map((prediction) => (
						<li key={prediction.place_id}>
							<button
								type="button"
								onMouseDown={(e) => e.preventDefault()}
								onClick={() => handlePick(prediction)}
								className="w-full text-left px-3 py-2 text-sm text-foreground hover:bg-muted/50 transition-colors"
							>
								{prediction.description}
							</button>
						</li>
					))}
				</ul>
			)}
		</div>
	);
};

export default AddressAutocompleteInput;
