/**
 * Jobs Hook with Real-time Updates
 *
 * Combines React Query with WebSocket for real-time job updates.
 * Automatically invalidates queries when WebSocket messages are received.
 */

import { useEffect, useCallback, useRef } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { AppState, type AppStateStatus } from 'react-native';
import { getJobs, getJobDetail } from '../api/jobs';
import { websocketService, type WebSocketMessage } from '../services/websocket';
import { useAuth } from './useAuth';
import type { JobsResponse, JobDetail, JobListItem } from '../types';

interface UseJobsOptions {
  startDate?: string;
  endDate?: string;
  enabled?: boolean;
}

/**
 * Hook for fetching jobs list with real-time updates
 */
export function useJobs(options: UseJobsOptions = {}) {
  const { startDate, endDate, enabled = true } = options;
  const { isAuthenticated } = useAuth();
  const queryClient = useQueryClient();
  const appState = useRef(AppState.currentState);

  // Track WebSocket connection status
  const wsConnectedRef = useRef(false);

  // Connect/disconnect WebSocket based on auth state and app state
  useEffect(() => {
    if (!isAuthenticated || !enabled) {
      websocketService.disconnect();
      wsConnectedRef.current = false;
      return;
    }

    // Connect on mount
    websocketService.connect();
    wsConnectedRef.current = true;

    // Handle app state changes (foreground/background)
    const subscription = AppState.addEventListener('change', (nextAppState: AppStateStatus) => {
      if (
        appState.current.match(/inactive|background/) &&
        nextAppState === 'active'
      ) {
        // App came to foreground - reconnect and refresh
        websocketService.connect();
        queryClient.invalidateQueries({ queryKey: ['jobs'] });
      } else if (nextAppState.match(/inactive|background/)) {
        // App going to background - disconnect to save battery
        websocketService.disconnect();
      }
      appState.current = nextAppState;
    });

    return () => {
      subscription.remove();
      websocketService.disconnect();
      wsConnectedRef.current = false;
    };
  }, [isAuthenticated, enabled, queryClient]);

  // Handle WebSocket messages
  useEffect(() => {
    if (!isAuthenticated || !enabled) {
      return;
    }

    const handleMessage = (message: WebSocketMessage) => {
      switch (message.type) {
        case 'event_created':
        case 'job_assigned':
          // New job - invalidate the jobs list
          queryClient.invalidateQueries({ queryKey: ['jobs'] });
          break;

        case 'event_updated':
        case 'event_status_changed':
          // Update optimistically if we have the data
          if (message.event?.id) {
            // Invalidate specific job detail
            queryClient.invalidateQueries({ queryKey: ['job', message.event.id] });

            // Invalidate ALL jobs queries (matches ['jobs', ...] with any params)
            queryClient.invalidateQueries({ queryKey: ['jobs'] });
          }
          break;

        case 'event_deleted':
        case 'job_unassigned':
          // Job removed - remove from cache and invalidate
          if (message.event_id) {
            queryClient.removeQueries({ queryKey: ['job', message.event_id] });
            queryClient.setQueryData<JobsResponse>(['jobs'], (oldData) => {
              if (!oldData) return oldData;
              return {
                ...oldData,
                jobs: oldData.jobs.filter((job: JobListItem) => job.id !== message.event_id),
                count: oldData.count - 1,
              };
            });
          }
          break;

        default:
          break;
      }
    };

    const removeHandler = websocketService.addHandler(handleMessage);
    return removeHandler;
  }, [isAuthenticated, enabled, queryClient]);

  // Build params object for date range query
  const queryParams = {
    ...(startDate && { startDate }),
    ...(endDate && { endDate }),
  };

  // Fetch jobs using React Query
  const query = useQuery({
    queryKey: ['jobs', queryParams],
    queryFn: () => getJobs(queryParams),
    enabled: isAuthenticated && enabled && !!startDate && !!endDate,
    staleTime: 1000 * 60 * 2, // 2 minutes (WebSocket keeps it fresh)
    refetchOnWindowFocus: true,
    refetchOnReconnect: true,
  });

  // Refresh function for pull-to-refresh
  const refresh = useCallback(async () => {
    await query.refetch();
  }, [query]);

  return {
    ...query,
    refresh,
    isConnected: wsConnectedRef.current,
  };
}

/**
 * Hook for fetching a single job with real-time updates
 */
export function useJob(jobId: number | null, options: { enabled?: boolean } = {}) {
  const { enabled = true } = options;
  const { isAuthenticated } = useAuth();
  const queryClient = useQueryClient();

  // Subscribe to this specific event for updates
  useEffect(() => {
    if (!jobId || !isAuthenticated || !enabled) {
      return;
    }

    websocketService.subscribeToEvent(jobId);

    return () => {
      websocketService.unsubscribeFromEvent(jobId);
    };
  }, [jobId, isAuthenticated, enabled]);

  // Handle WebSocket messages for this job
  useEffect(() => {
    if (!jobId || !isAuthenticated || !enabled) {
      return;
    }

    const handleMessage = (message: WebSocketMessage) => {
      // Only handle messages for this specific job
      const messageJobId = message.event?.id || message.event_id;
      if (messageJobId !== jobId) {
        return;
      }

      switch (message.type) {
        case 'event_updated':
        case 'event_status_changed':
          // Refetch the job detail
          queryClient.invalidateQueries({ queryKey: ['job', jobId] });
          break;

        case 'event_deleted':
        case 'job_unassigned':
          // Job was deleted/unassigned - you might want to navigate away
          queryClient.removeQueries({ queryKey: ['job', jobId] });
          break;

        default:
          break;
      }
    };

    const removeHandler = websocketService.addHandler(handleMessage);
    return removeHandler;
  }, [jobId, isAuthenticated, enabled, queryClient]);

  // Fetch job detail using React Query
  const query = useQuery({
    queryKey: ['job', jobId],
    queryFn: () => getJobDetail(jobId!),
    enabled: isAuthenticated && enabled && !!jobId,
    staleTime: 1000 * 60 * 2, // 2 minutes
  });

  // Refresh function
  const refresh = useCallback(async () => {
    await query.refetch();
  }, [query]);

  return {
    ...query,
    refresh,
  };
}

export default useJobs;
