'use client';

/**
 * AppStateMachine Provider
 *
 * Wraps the application with the app-level state machine.
 * Provides state and send function to all child components via context.
 * Also handles responsive mode detection and route synchronization.
 */

import { useEffect, useRef } from 'react';
import { useSelector } from '@xstate/react';
import { createActor } from 'xstate';
import { usePathname, useRouter } from 'next/navigation';
import { useMediaQuery } from '@mantine/hooks';
import { appMachine } from '@/lib/app-machine';
import { AppMachineContext } from '@/hooks/useAppMachine';

// Create the actor singleton outside the component to persist state
const appActor = createActor(appMachine);
appActor.start();

export function AppStateMachineProvider({ children }: { children: React.ReactNode }) {
  const state = useSelector(appActor, (state) => state);
  const send = appActor.send;
  const pathname = usePathname();
  const router = useRouter();

  // Track if this is the initial mount
  const isInitializedRef = useRef(false);
  // Track the last path we navigated to, to prevent loops
  const lastNavigatedPathRef = useRef<string | null>(null);

  // Detect mobile vs desktop
  const isMobile = useMediaQuery('(max-width: 768px)');

  // Update mode in state machine
  useEffect(() => {
    send({ type: 'SET_MODE', mode: isMobile ? 'mobile' : 'desktop' });
  }, [isMobile, send]);

  // Initialize state machine from URL on first mount ONLY
  useEffect(() => {
    if (isInitializedRef.current) return;

    console.log('[App Provider] Initializing state from URL:', pathname);

    // Determine which state the current path corresponds to
    let initialEvent: string | null = null;

    if (pathname === '/chat') {
      initialEvent = 'NAVIGATE_TO_CONVO';
    } else if (pathname === '/edit') {
      initialEvent = 'NAVIGATE_TO_EDIT';
    } else if (pathname === '/galaxy') {
      initialEvent = 'NAVIGATE_TO_GALAXY';
    }

    // Send the event to initialize state from URL
    if (initialEvent) {
      console.log('[App Provider] Setting initial state:', initialEvent);
      send({ type: initialEvent as any });
    }

    // Mark as initialized AFTER sending the event
    isInitializedRef.current = true;
  }, [pathname, send]); // Remove 'state' from dependencies!

  // State machine is source of truth: sync state → URL only
  // This effect ONLY runs when state changes, not when pathname changes
  useEffect(() => {
    // Don't navigate until initialized
    if (!isInitializedRef.current) {
      return;
    }

    let targetPath: string | null = null;

    if (state.matches('convo')) {
      targetPath = '/chat';
    } else if (state.matches('edit')) {
      targetPath = '/edit';
    } else if (state.matches('galaxy')) {
      targetPath = '/galaxy';
    }

    // ONLY navigate if we have a target path and haven't already navigated to it
    if (targetPath && targetPath !== lastNavigatedPathRef.current) {
      console.log('[App Provider] State machine navigating to:', targetPath);
      lastNavigatedPathRef.current = targetPath;
      router.push(targetPath);
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [state.value]); // ONLY depend on state.value, NOT pathname or router!

  // Log state changes
  useEffect(() => {
    console.log('[App Provider] State:', state.value);
    console.log('[App Provider] Tags:', Array.from(state.tags));
    console.log('[App Provider] Context:', state.context);
  }, [state]);

  return (
    <AppMachineContext.Provider value={appActor}>
      {children}
    </AppMachineContext.Provider>
  );
}
