'use client';

import { useAuth, useUser } from '@clerk/nextjs';
import { honeypot } from '@honeypot-run/core';
import { useStatsigClient } from '@statsig/react-bindings';
import { usePathname } from 'next/navigation';
import { useCallback, useEffect, useRef, useState } from 'react';

import { useStores } from '@/app/(root)/AppProviders';
import { initHoneypot } from '@/logging/eventSubscribers/honeypot';
import {
  hasAntiAbuseTrackingExpired,
  setAntiAbuseTracking,
} from '@/utils/antiAbuse';
import { CLOUDFLARE_TURNSTILE_SITE_KEY_AUTH } from '@/utils/constants';

// Extend window interface for Turnstile
declare global {
  interface Window {
    turnstile?: {
      render: (container: string, options: any) => void;
      remove: (element: Element) => void;
    };
    turnstileResolve?: (result: any) => void;
    turnstileReject?: (error: any) => void;
  }
}

const ANTI_ABUSE_GATE_NAME = 'anti-abuse-checks-enabled';
const CHECK_GATE = true;

export default function AntiAbuseTracker() {
  const { isLoaded, isSignedIn } = useAuth();
  const { user: clerkUser } = useUser();
  const statsigClient = useStatsigClient();
  const { apiClient } = useStores();
  const pathname = usePathname();

  // Track current challenge data for storing token after success
  const [currentTrackingKey, setCurrentTrackingKey] = useState<string | null>(
    null
  );

  const turnstileMounted = useRef(false);
  const turnstileRetries = useRef(0);

  // Update onTurnstileSuccess to include sitekey and use onTurnstileResult
  const onTurnstileResult = (
    status: 'success' | 'error' | 'timeout' | 'unsupported',
    token?: string,
    error?: any
  ) => {
    setCurrentTrackingKey(null);

    if (status === 'success' && token) {
      // Store token for successful challenges
      if (currentTrackingKey) {
        setAntiAbuseTracking(currentTrackingKey, token);
      }

      // Resolve with success response including sitekey
      if (window.turnstileResolve) {
        window.turnstileResolve({
          status: 'success',
          token,
          sitekey: CLOUDFLARE_TURNSTILE_SITE_KEY_AUTH,
        });
      }
    } else {
      // Reject for any non-success status
      if (window.turnstileReject) {
        window.turnstileReject({
          status,
          error: error || `Turnstile ${status}`,
          sitekey: CLOUDFLARE_TURNSTILE_SITE_KEY_AUTH,
        });
      }
    }
  };

  // Load Turnstile script directly
  useEffect(() => {
    if (turnstileMounted.current) return;
    if (typeof window !== 'undefined' && !window.turnstile) {
      // Load the Turnstile script (no callback needed)
      const script = document.createElement('script');
      script.src =
        'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
      script.async = true;
      script.defer = true;
      document.head.appendChild(script);
      turnstileMounted.current = true;
    }
  }, []);

  const getHoneypotToken = async (
    payload: Record<string, any>
  ): Promise<any> => {
    try {
      await initHoneypot();
      honeypot.identify(payload.user_id);
      const response = await honeypot.track('Auth check', payload);
      return { sealed: response?.sealed };
    } catch (error) {
      return { error: 'Initialization error' };
    }
  };

  // Render invisible Turnstile (similar to MusicianCreate but invisible)
  const getTurnstileToken = (trackingKey: string): Promise<any> => {
    return new Promise((resolve, reject) => {
      const startTime = Date.now();
      turnstileRetries.current = 0; // Reset retry counter for each new attempt

      const attemptTurnstile = () => {
        if (!window.turnstile) {
          // Retry after 100ms if not loaded yet, up to 5 seconds
          setTimeout(() => {
            if (Date.now() - startTime > 5000) {
              reject(new Error('Turnstile failed to load within 5 seconds'));
            } else {
              attemptTurnstile();
            }
          }, 100);
          return;
        }

        // Store resolve/reject for later use in callbacks
        window.turnstileResolve = resolve;
        window.turnstileReject = reject;

        // Set the current tracking key
        setCurrentTrackingKey(trackingKey);

        // Clean up any existing widget first
        const existingContainer = document.getElementById('aa-turnstile');
        if (existingContainer) {
          // Remove the Turnstile widget if it exists
          if (window.turnstile) {
            try {
              window.turnstile.remove(existingContainer);
            } catch (e) {
              //console.log('No widget to remove');
            }
          }
          // Remove the DOM element
          existingContainer.remove();
        }

        // Now create fresh container
        const turnstileContainer = document.createElement('div');
        turnstileContainer.id = 'aa-turnstile';
        turnstileContainer.className = 'cf-turnstile fixed';
        turnstileContainer.style.width = '300px';
        turnstileContainer.style.height = '65px';
        document.body.appendChild(turnstileContainer);

        if (window.turnstile && turnstileContainer) {
          window.turnstile.render(`#${turnstileContainer.id}`, {
            sitekey: CLOUDFLARE_TURNSTILE_SITE_KEY_AUTH,
            callback: (token: any) => onTurnstileResult('success', token),
            'error-callback': (error: any) =>
              onTurnstileResult('error', undefined, error),
            'timeout-callback': () => onTurnstileResult('timeout'),
            'unsupported-callback': () => onTurnstileResult('unsupported'),
            theme: 'dark',
            size: 'compact',
          });
        } else {
          turnstileRetries.current++;
          if (turnstileRetries.current < 50) {
            // 50 retries = 5 seconds
            setTimeout(() => {
              attemptTurnstile();
            }, 100);
          } else {
            setCurrentTrackingKey(null);
            reject(new Error('Failed to load Turnstile after 50 retries'));
          }
        }
      };

      attemptTurnstile();
    });
  };

  const updateTokens = async (
    payload: Record<string, any>,
    trackingKey: string
  ): Promise<void> => {
    try {
      // Get Turnstile token and Honeypot response in parallel with 5s timeout
      const [honeypotResponse, turnstileResponse] = (await Promise.race([
        Promise.all([
          getHoneypotToken(payload),
          getTurnstileToken(trackingKey),
        ]),
        new Promise((_, reject) =>
          setTimeout(
            () =>
              reject(new Error('Anti-abuse checks timed out after 10 seconds')),
            10000
          )
        ),
      ])) as [any, any];

      // Combine all data for API call
      const apiPayload = {
        ...payload,
        honeypot: honeypotResponse,
        turnstile: turnstileResponse,
        timestamp: Date.now(),
        userAgent: navigator.userAgent,
      };

      // Make API call with all data
      await (apiClient.POST as any)('/api/auth/verify-token', {
        body: apiPayload,
      });
    } catch (error) {
      console.error('Token checks failed or timed out:', error);
    }
  };

  const runAntiAbuseChecks = useCallback(
    async ({ clerkUser }: { clerkUser: any }) => {
      // Calculate time difference in minutes
      const now = Date.now();
      const createdAt = new Date(clerkUser.createdAt).getTime();
      const timeDiffMs = now - createdAt;
      const timeDiffMinutes = Math.round(timeDiffMs / (1000 * 60)); // Convert to minutes
      const isNewSignup = timeDiffMinutes < 5;

      // Use localStorage to track if we've already processed this signin
      const trackingKey = `_af-${clerkUser.id}`;

      // Only process if we haven't tracked this signin or tracking has expired AND gate is enabled
      if (
        hasAntiAbuseTrackingExpired(trackingKey) &&
        (!CHECK_GATE || statsigClient.checkGate(ANTI_ABUSE_GATE_NAME))
      ) {
        // Run Turnstile challenge for signin
        await updateTokens(
          {
            account_age_minutes: timeDiffMinutes,
            is_new_signup: isNewSignup,
            user_id: clerkUser.id,
            email: clerkUser.primaryEmailAddress?.emailAddress || '',
            phone: clerkUser.primaryPhoneNumber?.phoneNumber || '',
            timestamp: Date.now(),
          },
          trackingKey
        );

        // Set initial tracking entry (token will be added later on success)
        setAntiAbuseTracking(trackingKey);
      }
    },
    [apiClient, statsigClient]
  );

  useEffect(() => {
    if (!isLoaded || !isSignedIn || !clerkUser) return;

    runAntiAbuseChecks({ clerkUser });
  }, [isLoaded, isSignedIn, clerkUser, pathname, runAntiAbuseChecks]);

  return null;
}
