'use client';

import { useCallback, useState } from 'react';

import { useCfgRouter } from '@djangocfg/ui-nextjs/hooks';

import { apiAccounts } from '../../clients';
import { Analytics, AnalyticsCategory, AnalyticsEvent } from '../utils/analytics';
import { authLogger } from '../utils/logger';

export interface UseGithubAuthOptions {
  sourceUrl?: string;
  onSuccess?: (user: any, isNewUser: boolean) => void;
  onError?: (error: string) => void;
  /** Callback when 2FA is required */
  onRequires2FA?: (sessionId: string, shouldPrompt2FA: boolean) => void;
  redirectUrl?: string;
  /** Skip automatic redirect after success (caller handles navigation) */
  skipRedirect?: boolean;
}

export interface UseGithubAuthReturn {
  isLoading: boolean;
  error: string | null;
  startGithubAuth: () => Promise<void>;
  handleGithubCallback: (code: string, state: string) => Promise<void>;
}

/**
 * Hook for GitHub OAuth authentication flow.
 *
 * Usage:
 * 1. Call startGithubAuth() to redirect user to GitHub
 * 2. After GitHub redirects back, call handleGithubCallback(code, state)
 *
 * @example
 * ```tsx
 * const { isLoading, error, startGithubAuth } = useGithubAuth({
 *   onSuccess: (user) => router.push('/dashboard'),
 *   onError: (error) => console.error(error),
 * });
 *
 * <Button onClick={startGithubAuth} disabled={isLoading}>
 *   Continue with GitHub
 * </Button>
 * ```
 */
export const useGithubAuth = (options: UseGithubAuthOptions = {}): UseGithubAuthReturn => {
  const { sourceUrl, onSuccess, onError, onRequires2FA, redirectUrl, skipRedirect = false } = options;
  const router = useCfgRouter();

  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  /**
   * Start GitHub OAuth flow - redirects user to GitHub authorization page.
   */
  const startGithubAuth = useCallback(async () => {
    setIsLoading(true);
    setError(null);

    try {
      authLogger.info('Starting GitHub OAuth flow...');

      // Track OAuth start
      Analytics.event(AnalyticsEvent.AUTH_OAUTH_START, {
        category: AnalyticsCategory.AUTH,
        label: 'github',
      });

      // Call API to get authorization URL
      // The API will auto-generate redirect_uri from config if not provided
      const response = await apiAccounts.oauth.accountsOauthGithubAuthorizeCreate({
        source_url: sourceUrl || (typeof window !== 'undefined' ? window.location.href : ''),
      });

      if (!response.authorization_url) {
        throw new Error('Failed to get authorization URL');
      }

      authLogger.info('Redirecting to GitHub...', response.authorization_url);

      // Store state in sessionStorage for verification on callback
      if (typeof window !== 'undefined') {
        sessionStorage.setItem('oauth_state', response.state);
        sessionStorage.setItem('oauth_provider', 'github');
      }

      // Redirect to GitHub
      window.location.href = response.authorization_url;

    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to start GitHub authentication';
      authLogger.error('GitHub OAuth start error:', err);
      setError(errorMessage);
      onError?.(errorMessage);

      // Track OAuth error
      Analytics.event(AnalyticsEvent.AUTH_OAUTH_FAIL, {
        category: AnalyticsCategory.AUTH,
        label: 'github',
      });
    } finally {
      setIsLoading(false);
    }
  }, [sourceUrl, onError]);

  /**
   * Handle GitHub OAuth callback - exchanges code for JWT tokens.
   *
   * @param code - Authorization code from GitHub callback
   * @param state - State token for CSRF verification
   */
  const handleGithubCallback = useCallback(async (code: string, state: string) => {
    setIsLoading(true);
    setError(null);

    try {
      authLogger.info('Processing GitHub OAuth callback...');

      // Verify state matches what we stored
      if (typeof window !== 'undefined') {
        const storedState = sessionStorage.getItem('oauth_state');
        if (storedState && storedState !== state) {
          throw new Error('Invalid OAuth state - possible CSRF attack');
        }
        // Clear stored state
        sessionStorage.removeItem('oauth_state');
        sessionStorage.removeItem('oauth_provider');
      }

      // Exchange code for tokens
      // The API will auto-generate redirect_uri from config if not provided
      const response = await apiAccounts.oauth.accountsOauthGithubCallbackCreate({
        code,
        state,
      });

      // Check if 2FA is required
      if (response.requires_2fa && response.session_id) {
        authLogger.info('GitHub OAuth requires 2FA, session:', response.session_id);

        // Track 2FA requirement
        Analytics.event(AnalyticsEvent.AUTH_OAUTH_START, {
          category: AnalyticsCategory.AUTH,
          label: 'github-2fa-required',
        });

        // Call 2FA callback
        onRequires2FA?.(response.session_id, response.should_prompt_2fa || false);
        return;
      }

      if (!response.access || !response.refresh) {
        throw new Error('Invalid response from OAuth callback');
      }

      authLogger.info('GitHub OAuth successful, user:', response.user);

      // Save tokens using API client
      apiAccounts.setToken(response.access, response.refresh);

      // Track successful OAuth
      Analytics.event(AnalyticsEvent.AUTH_LOGIN_SUCCESS, {
        category: AnalyticsCategory.AUTH,
        label: 'github',
      });

      // Set user ID for future tracking
      if (response.user?.id) {
        Analytics.setUser(String(response.user.id));
      }

      // Call success callback
      onSuccess?.(response.user, response.is_new_user || false);

      // Redirect (unless skipRedirect is true)
      if (!skipRedirect) {
        // Use hardPush for full page reload - ensures all React contexts reinitialize
        const finalRedirectUrl = redirectUrl || '/dashboard';
        router.hardPush(finalRedirectUrl);
      }

    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'GitHub authentication failed';
      authLogger.error('GitHub OAuth callback error:', err);
      setError(errorMessage);
      onError?.(errorMessage);

      // Track OAuth error
      Analytics.event(AnalyticsEvent.AUTH_OAUTH_FAIL, {
        category: AnalyticsCategory.AUTH,
        label: 'github',
      });
    } finally {
      setIsLoading(false);
    }
  }, [onSuccess, onError, redirectUrl, router]);

  return {
    isLoading,
    error,
    startGithubAuth,
    handleGithubCallback,
  };
};
