import { useState, useEffect, useCallback, useRef } from 'react';
import workOrderService from '../services/workOrderService';
import type { WorkOrder, WorkOrderFilters, WorkOrderListQuery, CreateWorkOrderData } from '../services/workOrderService';

/**
 * Merge user filters with permission filters
 * Permission filters take precedence for security
 */
const mergeFilters = (
  userQuery: WorkOrderFilters | WorkOrderListQuery | any[] | undefined,
  permissionFilters: Record<string, any>
): WorkOrderFilters | WorkOrderListQuery | any[] => {
  if (Array.isArray(userQuery)) {
    return userQuery;
  }

  const baseFilters =
    userQuery && 'or_filters' in userQuery
      ? { ...(userQuery.filters as Record<string, any> | undefined) }
      : { ...((userQuery as WorkOrderFilters | undefined) || {}) };

  const merged: Record<string, any> = { ...baseFilters };
  const orFilters =
    userQuery && 'or_filters' in userQuery ? userQuery.or_filters : undefined;

  // Apply permission filters (they take precedence for security)
  for (const [field, value] of Object.entries(permissionFilters)) {
    if (!merged[field]) {
      merged[field] = value;
    } else if (Array.isArray(value) && value[0] === 'in') {
      const permittedValues = value[1] as string[];
      const userValue = merged[field];

      if (typeof userValue === 'string') {
        if (!permittedValues.includes(userValue)) {
          merged[field] = ['in', []];
        }
      } else if (Array.isArray(userValue) && userValue[0] === 'in') {
        const userValues = userValue[1] as string[];
        const intersection = userValues.filter(v => permittedValues.includes(v));
        merged[field] = ['in', intersection];
      } else {
        merged[field] = value;
      }
    }
  }

  if (orFilters?.length) {
    return { filters: merged, or_filters: orFilters };
  }

  return merged;
};

/**
 * Hook to fetch list of work orders with filters, pagination, and permission-based filtering
 */
export function useWorkOrders(
  filters?: WorkOrderFilters | WorkOrderListQuery | any[],
  limit: number = 20,
  offset: number = 0,
  orderBy?: string,
  permissionFilters: Record<string, any> = {}
) {
  const [workOrders, setWorkOrders] = useState<WorkOrder[]>([]);
  const [totalCount, setTotalCount] = useState(0);
  const [hasMore, setHasMore] = useState(false);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [refetchTrigger, setRefetchTrigger] = useState(0);
  const hasAttemptedRef = useRef(false);

  // Stringify filters to prevent object reference changes from causing re-renders
  const filtersJson = JSON.stringify(filters);
  const permissionFiltersJson = JSON.stringify(permissionFilters); // ← NEW

  useEffect(() => {
    // Prevent fetching if already attempted and has error
    if (hasAttemptedRef.current && error) {
      return;
    }

    let isCancelled = false;
    hasAttemptedRef.current = true;
    
    const fetchWorkOrders = async () => {
      try {
        setLoading(true);
        
        // ✅ NEW: Merge user filters with permission filters
        const mergedFilters = Array.isArray(filters)
          ? filters
          : mergeFilters(filters, permissionFilters);
        
        console.log('[useWorkOrders] User filters:', filters);
        console.log('[useWorkOrders] Permission filters:', permissionFilters);
        console.log('[useWorkOrders] Merged filters:', mergedFilters);
        
        const response = await workOrderService.getWorkOrders(mergedFilters, undefined, limit, offset, orderBy);
        
        if (!isCancelled) {
          setWorkOrders(response.work_orders);
          setTotalCount(response.total_count);
          setHasMore(response.has_more);
          setError(null);
        }
      } catch (err) {
        if (!isCancelled) {
          const errorMessage = err instanceof Error ? err.message : 'Failed to fetch work orders';
          
          // Check if it's a 417 error (API not deployed)
          if (errorMessage.includes('417') || errorMessage.includes('Expectation Failed') || errorMessage.includes('has no attribute')) {
            setError('API endpoint not deployed or misconfigured. Please check FIX_417_ERROR.md for solutions.');
          } else {
            setError(errorMessage);
          }
          
          // Set empty arrays
          setWorkOrders([]);
          setTotalCount(0);
          setHasMore(false);
        }
      } finally {
        if (!isCancelled) {
          setLoading(false);
        }
      }
    };
    
    fetchWorkOrders();
    
    return () => {
      isCancelled = true;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [filtersJson, permissionFiltersJson, limit, offset, orderBy, refetchTrigger]); // ← Added permissionFiltersJson

  const refetch = useCallback(() => {
    hasAttemptedRef.current = false; // Reset to allow refetch
    setRefetchTrigger(prev => prev + 1);
  }, []);

  return { workOrders, totalCount, hasMore, loading, error, refetch };
}

/**
 * Hook to fetch a single work order by name
 */
export function useWorkOrderDetails(workOrderName: string | null) {
  const [workOrder, setWorkOrder] = useState<WorkOrder | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchWorkOrder = useCallback(async () => {
    if (!workOrderName) {
      setWorkOrder(null);
      setLoading(false);
      return;
    }

    try {
      setLoading(true);
      setError(null);
      
      const data = await workOrderService.getWorkOrderDetails(workOrderName);
      setWorkOrder(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to fetch work order details');
    } finally {
      setLoading(false);
    }
  }, [workOrderName]);

  useEffect(() => {
    fetchWorkOrder();
  }, [fetchWorkOrder]);

  const refetch = useCallback(() => {
    fetchWorkOrder();
  }, [fetchWorkOrder]);

  return { workOrder, loading, error, refetch };
}

/**
 * Hook to manage work order operations (create, update, delete)
 */
export function useWorkOrderMutations() {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const createWorkOrder = async (workOrderData: CreateWorkOrderData) => {
    try {
      setLoading(true);
      setError(null);
      
      console.log('[useWorkOrderMutations] Creating work order with data:', workOrderData);
      const response = await workOrderService.createWorkOrder(workOrderData);
      console.log('[useWorkOrderMutations] Create work order response:', response);
      
      if (response.success) {
        return response.work_order;
      } else {
        // Include the backend error message if available
        const backendError = (response as any).error || 'Failed to create work order';
        throw new Error(backendError);
      }
    } catch (err) {
      console.error('[useWorkOrderMutations] Create work order error:', err);
      const errorMessage = err instanceof Error ? err.message : 'Failed to create work order';
      setError(errorMessage);
      throw err;
    } finally {
      setLoading(false);
    }
  };

  const updateWorkOrder = async (workOrderName: string, workOrderData: Partial<CreateWorkOrderData>) => {
    try {
      setLoading(true);
      setError(null);
      
      console.log('[useWorkOrderMutations] Updating work order:', workOrderName, 'with data:', workOrderData);
      const response = await workOrderService.updateWorkOrder(workOrderName, workOrderData);
      console.log('[useWorkOrderMutations] Update work order response:', response);
      
      if (response.success) {
        return response.work_order;
      } else {
        // Include the backend error message if available
        const backendError = (response as any).error || 'Failed to update work order';
        throw new Error(backendError);
      }
    } catch (err) {
      console.error('[useWorkOrderMutations] Update work order error:', err);
      const errorMessage = err instanceof Error ? err.message : 'Failed to update work order';
      setError(errorMessage);
      throw err;
    } finally {
      setLoading(false);
    }
  };

  const deleteWorkOrder = async (workOrderName: string) => {
    try {
      setLoading(true);
      setError(null);
      
      const response = await workOrderService.deleteWorkOrder(workOrderName);
      
      if (!response.success) {
        throw new Error('Failed to delete work order');
      }
      
      return response;
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to delete work order';
      setError(errorMessage);
      throw err;
    } finally {
      setLoading(false);
    }
  };

  const submitWorkOrder = async (workOrderName: string) => {
    try {
      setLoading(true);
      setError(null);
      
      console.log('[useWorkOrderMutations] Submitting work order:', workOrderName);
      const response = await workOrderService.submitWorkOrder(workOrderName);
      console.log('[useWorkOrderMutations] Submit work order response:', response);
      
      return response;
    } catch (err) {
      console.error('[useWorkOrderMutations] Submit work order error:', err);
      const errorMessage = err instanceof Error ? err.message : 'Failed to submit work order';
      setError(errorMessage);
      throw err;
    } finally {
      setLoading(false);
    }
  };

  const updateStatus = async (workOrderName: string, repairStatus?: string, workflowState?: string) => {
    try {
      setLoading(true);
      setError(null);
      
      const response = await workOrderService.updateWorkOrderStatus(workOrderName, repairStatus, workflowState);
      
      if (response.success) {
        return response.work_order;
      } else {
        throw new Error('Failed to update work order status');
      }
    } catch (err) {
      const errorMessage = err instanceof Error ? err.message : 'Failed to update status';
      setError(errorMessage);
      throw err;
    } finally {
      setLoading(false);
    }
  };

  return { createWorkOrder, updateWorkOrder, deleteWorkOrder, submitWorkOrder, updateStatus, loading, error };
}

/**
 * Hook to fetch work order filter options
 */
export function useWorkOrderFilters() {
  const [filters, setFilters] = useState<any | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchFilters = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);
      
      const data = await workOrderService.getWorkOrderFilters();
      setFilters(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to fetch filters');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchFilters();
  }, [fetchFilters]);

  const refetch = useCallback(() => {
    fetchFilters();
  }, [fetchFilters]);

  return { filters, loading, error, refetch };
}

/**
 * Hook to fetch work order statistics
 */
export function useWorkOrderStats() {
  const [stats, setStats] = useState<any | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchStats = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);
      
      const data = await workOrderService.getWorkOrderStats();
      setStats(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Failed to fetch statistics');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    fetchStats();
  }, [fetchStats]);

  const refetch = useCallback(() => {
    fetchStats();
  }, [fetchStats]);

  return { stats, loading, error, refetch };
}

/**
 * Hook for work order search
 */
export function useWorkOrderSearch() {
  const [results, setResults] = useState<WorkOrder[]>([]);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  const search = useCallback(async (searchTerm: string, limit: number = 10) => {
    if (!searchTerm.trim()) {
      setResults([]);
      return;
    }

    try {
      setLoading(true);
      setError(null);
      
      const data = await workOrderService.searchWorkOrders(searchTerm, limit);
      setResults(data);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Search failed');
      setResults([]);
    } finally {
      setLoading(false);
    }
  }, []);

  const clearResults = useCallback(() => {
    setResults([]);
    setError(null);
  }, []);

  return { results, loading, error, search, clearResults };
}