import { getAccessToken } from "../utilities/apiHelpers.mjs";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { UdpWebSocketClient } from "udp-react-stencil-component-library";
//#region src/hooks/useUdpWebSocket.ts
/**
* React hook for managing WebSocket connections with automatic connection handling,
* keep-alive support, and message management.
*
* @param url - The WebSocket URL to connect to (ws:// or wss://). If undefined, no connection is established.
* @param options - Configuration options for the WebSocket connection behavior.
*
* @returns An object containing:
* - `connected`: Boolean indicating if the WebSocket is currently connected
* - `lastMessage`: The most recent message received from the server
* - `lastError`: The most recent error event
* - `send`: Async function to send messages (auto-connects if not connected)
* - `reconnect`: Async function to manually reconnect the WebSocket
* - `close`: Function to close the WebSocket connection
* - `client`: Direct access to the underlying UdpWebSocketClient instance
*
* @example
* ```tsx
* // Basic usage
* const { connected, send } = useUdpWebSocket(
*   'wss://localhost:44371/UemService/api/v1/UdpWebSocket/21f2060a-1a09-4a03-81aa-4179db30b4eb/connect'
* );
*
* const handleSend = () => {
*   send({ payload: { message: "Hello world" } });
* };
* ```
*
* @example
* ```tsx
* // With message handling and keep-alive
* const { connected, lastMessage, send } = useUdpWebSocket(
*   'wss://localhost:44371/UemService/api/v1/UdpWebSocket/21f2060a-1a09-4a03-81aa-4179db30b4eb/connect',
*   {
*     onMessageReceived: (msg) => {
*       console.log('Received:', msg);
*     },
*     onError: (error) => {
*       console.error('WebSocket error:', error);
*     },
*     onClose: () => {
*       console.log('Connection closed');
*     },
*     keepAliveIntervalSec: 30,  // Send ping every 30 seconds
*     keepAliveTimeoutMin: 10     // Auto-close after 10 minutes
*   }
* );
*
* useEffect(() => {
*   if (lastMessage) {
*     // Handle received message
*   }
* }, [lastMessage]);
* ```
*
* @remarks
* - The hook automatically establishes a connection when the URL is provided
* - Authentication tokens are automatically retrieved via `getAccessToken()`
* - The `send()` function will automatically connect if not already connected
* - Calling `close()` will close the connection; it will not auto-reconnect unless `reconnect()` is called
* - The connection is automatically cleaned up when the component unmounts
* - Keep-alive pings help maintain long-lived connections and detect dead connections
*/
function useUdpWebSocket(url, options = {}) {
	const { onMessageReceived, onError, onClose, keepAliveIntervalSec = 0, keepAliveTimeoutMin = 0 } = options;
	const initialRetryCountRef = useRef(0);
	const MAX_INIT_RETRIES = 5;
	const INIT_RETRY_DELAY = 300;
	const [client] = useState(() => new UdpWebSocketClient());
	const [connected, setConnected] = useState(false);
	const [lastMessage, setLastMessage] = useState(null);
	const [lastError, setLastError] = useState(null);
	const messageHandlerRef = useRef(onMessageReceived);
	const errorHandlerRef = useRef(onError);
	const closeHandlerRef = useRef(onClose);
	useEffect(() => {
		messageHandlerRef.current = onMessageReceived;
	}, [onMessageReceived]);
	useEffect(() => {
		errorHandlerRef.current = onError;
	}, [onError]);
	useEffect(() => {
		closeHandlerRef.current = onClose;
	}, [onClose]);
	const connect = useCallback(async () => {
		if (!url) return;
		const c = client;
		if (c.isConnected) return;
		const interval = (keepAliveIntervalSec || 0) * 1e3;
		const timeout = (keepAliveTimeoutMin || 0) * 60 * 1e3;
		await c.connect(url, getAccessToken, interval, timeout);
	}, [
		url,
		keepAliveIntervalSec,
		keepAliveTimeoutMin,
		client
	]);
	const send = useCallback(async (msg) => {
		const c = client;
		if (!c.isConnected) await connect();
		c.send(msg);
	}, [client, connect]);
	const close = useCallback(() => {
		client.close();
	}, [client]);
	const reconnect = useCallback(async () => {
		const c = client;
		c.close();
		setConnected(c.isConnected);
		await connect();
	}, [client, connect]);
	useEffect(() => {
		if (!url) return;
		const c = client;
		initialRetryCountRef.current = 0;
		c.onMessageReceived((msg) => {
			setLastMessage(msg);
			messageHandlerRef.current?.(msg);
		});
		c.onOpen(() => {
			setConnected(c.isConnected);
		});
		c.onError((e) => {
			setLastError(e);
			errorHandlerRef.current?.(e);
		});
		c.onClose((e) => {
			if (!connected && initialRetryCountRef.current < MAX_INIT_RETRIES) {
				initialRetryCountRef.current++;
				setTimeout(() => connect(), INIT_RETRY_DELAY);
			}
			closeHandlerRef.current?.(e);
			setConnected(c.isConnected);
		});
		connect().catch(() => {
			console.warn("WebSocket initial connection failed");
		});
		initialRetryCountRef.current = MAX_INIT_RETRIES;
		return () => {
			c.close();
		};
	}, [
		url,
		client,
		connect
	]);
	return useMemo(() => ({
		connected,
		lastMessage,
		lastError,
		send,
		reconnect,
		close,
		client
	}), [
		connected,
		lastMessage,
		lastError,
		send,
		reconnect,
		close,
		client
	]);
}
//#endregion
export { useUdpWebSocket };

//# sourceMappingURL=useUdpWebSocket.mjs.map