
import React, { useEffect, useRef } from 'react';
import { useLocation, useNavigate, useSearchParams } from 'react-router-dom';
import {
    getHostExternalIdentityProvider,
    HOST_AUTH_PROVIDER_IDS,
    isHostReservedAuthProviderId,
    Logger,
    type HostOAuthCallbackPresentationProps,
} from '@nexuscrm/host-sdk';

function parseSavedProvider(provider: string | null): string | null {
    if (provider === HOST_AUTH_PROVIDER_IDS.GOOGLE || provider === HOST_AUTH_PROVIDER_IDS.NEXUSCRM) {
        return provider;
    }
    if (isHostReservedAuthProviderId(provider)) {
        return null;
    }
    if (getHostExternalIdentityProvider(provider)) {
        return provider;
    }
    return null;
}

export function OAuthCallback({ onLoginComplete, actions }: HostOAuthCallbackPresentationProps) {
    const [searchParams] = useSearchParams();
    const location = useLocation();
    const navigate = useNavigate();
    const [status, setStatus] = React.useState('loading');
    const [errorMessage, setErrorMessage] = React.useState('');
    // Guard against React Strict Mode double-invocation
    const processedRef = useRef(false);

    useEffect(() => {
        // Prevent double execution
        if (processedRef.current) return;

        const processCallback = async () => {
            const code = searchParams.get('code');
            const error = searchParams.get('error');
            const errorDescription = searchParams.get('error_description');
            const state = searchParams.get('state');
            const savedProvider = sessionStorage.getItem('oauth_provider');
            const savedState = sessionStorage.getItem('oauth_state');

            // Mark as processed immediately to stop race conditions
            processedRef.current = true;
            navigate(location.pathname, { replace: true });

            if (error) {
                sessionStorage.removeItem('oauth_provider');
                sessionStorage.removeItem('oauth_state');
                sessionStorage.removeItem('oauth_authorize_continue');
                Logger.error('OAuth Error', { error, errorDescription });
                navigate(`/?error=${encodeURIComponent(errorDescription || error)}`, { replace: true });
                return;
            }

            if (!code) {
                sessionStorage.removeItem('oauth_authorize_continue');
                navigate('/?error=No authorization code found', { replace: true });
                return;
            }

            const provider = parseSavedProvider(savedProvider);
            sessionStorage.removeItem('oauth_provider');
            sessionStorage.removeItem('oauth_state');
            if (provider !== HOST_AUTH_PROVIDER_IDS.GOOGLE) {
                sessionStorage.removeItem('oauth_authorize_continue');
            }

            if (!savedState || !state || state !== savedState) {
                sessionStorage.removeItem('oauth_authorize_continue');
                navigate('/?error=Invalid OAuth state — possible CSRF attack', { replace: true });
                return;
            }

            if (!provider) {
                sessionStorage.removeItem('oauth_authorize_continue');
                navigate('/?error=Missing or unsupported OAuth provider', { replace: true });
                return;
            }

            try {
                // savedState has already been matched with the callback value.
                // Pass it across the host boundary explicitly because storage
                // cleanup above must not erase the server-owned transaction
                // before /google/token can consume it.
                const result = await actions.exchangeOAuthCode(provider, code, savedState);

                // Login successful — use callback to update RuntimeContext (avoids full page reload)
                if (onLoginComplete && result) {
                    const shouldNavigateHome = await onLoginComplete(result.token, result.instanceUrl);
                    if (shouldNavigateHome !== false) {
                        navigate('/', { replace: true });
                    }
                } else {
                    window.location.replace('/');
                }
            } catch (err: unknown) {
                Logger.error('OAuth Exchange Failed', {}, err);
                setStatus('error');
                const error = err as { message?: string; data?: { error_description?: string; message?: string } };
                const msg = error.message || 'Authentication failed';
                const detail = error.data && (error.data.error_description || error.data.message || JSON.stringify(error.data));
                setErrorMessage(detail ? `${msg}: ${detail}` : msg);
            }
        };

        processCallback();
    }, [actions, location.pathname, searchParams, navigate, onLoginComplete]);

    const handleRetry = () => {
        navigate('/login', { replace: true });
    };

    if (status === 'error') {
        return (
            <div className="min-h-screen flex items-center justify-center bg-gray-50">
                <div className="text-center p-6 bg-white rounded-lg shadow-md">
                    <h2 className="text-2xl font-semibold text-red-600 mb-4">Authentication Failed</h2>
                    <p className="text-gray-700 mb-6">{errorMessage}</p>
                    <button
                        onClick={handleRetry}
                        className="px-6 py-2 bg-indigo-600 text-white font-medium rounded-md hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-indigo-500 focus:ring-offset-2"
                    >
                        Try Again
                    </button>
                </div>
            </div>
        );
    }

    return (
        <div className="min-h-screen flex items-center justify-center bg-gray-50">
            <div className="text-center">
                <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-indigo-600 mx-auto mb-4"></div>
                <h2 className="text-xl font-semibold text-gray-900">Authenticating...</h2>
                <p className="text-gray-500 mt-2">Please wait while we complete the secure login.</p>
            </div>
        </div>
    );
}
