import React, { createContext, useContext, useState, useEffect } from 'react';
import type { FoodItem, Category, Stall } from '../types';

interface FoodContextType {
  categories: Category[];
  foodItems: FoodItem[];
  stalls: Stall[];
  isLoading: boolean;
  error: string | null;
  refreshData: () => Promise<void>;
}

const FoodContext = createContext<FoodContextType | undefined>(undefined);

const API_BASE_URL = `http://${window.location.hostname}:8080/api`;

const EMOJIS = ['🍦', '🍪', '🧃', '🍫', '🥨', '🥐', '🍹', '📦', '🍳', '🍱', '🍔', '🍕', '🥗', '🍲'];
const COLORS = ['#FFF0F6', '#FFF7ED', '#FFFFEB', '#FDF3EF', '#F0FDF4', '#FEFCE8', '#EFF6FF'];

export const FoodProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [categories, setCategories] = useState<Category[]>([]);
  const [foodItems, setFoodItems] = useState<FoodItem[]>([]);
  const [stalls, setStalls] = useState<Stall[]>([]);
  const [isLoading, setIsLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  const fetchData = async () => {
    setIsLoading(true);
    setError(null);
    try {
      const [baseItemsRes, productsRes, stallsRes] = await Promise.all([
        fetch(`${API_BASE_URL}/base-items?size=100`, { cache: 'no-store' }),
        fetch(`${API_BASE_URL}/products?size=100`, { cache: 'no-store' }),
        fetch(`${API_BASE_URL}/stalls/active`, { cache: 'no-store' })
      ]);

      if (!baseItemsRes.ok || !productsRes.ok || !stallsRes.ok) {
        throw new Error('Failed to fetch data from server');
      }

      const baseItemsDataRaw = await baseItemsRes.json();
      const productsDataRaw = await productsRes.json();
      const stallsData = await stallsRes.json();

      const baseItemsData = baseItemsDataRaw.content || baseItemsDataRaw;
      const productsData = productsDataRaw.content || productsDataRaw;

      // Map BaseItems to Categories
      const mappedCategories: Category[] = baseItemsData.map((item: any, index: number) => ({
        id: item.id.toString(),
        name: item.name,
        description: item.description,
        emoji: EMOJIS[index % EMOJIS.length],
        image: item.imageData?.trim() ? (item.imageData.trim().startsWith('data:') ? item.imageData.trim() : `data:image/png;base64,${item.imageData.trim()}`) : '', 
        color: COLORS[index % COLORS.length]
      }));

      // Map Stalls and build a product-to-stall lookup map
      const productToStallMap: Record<string, { id: string, name: string }> = {};
      const categoryToStallMap: Record<string, { id: string, name: string }> = {};

      const mappedStalls: Stall[] = stallsData.map((item: any) => {
        const stallInfo = { id: item.id.toString(), name: item.name };
        
        // Map category/baseItems to this stall for indirect lookup
        if (item.baseItems) {
          item.baseItems.forEach((bi: any) => {
            if (!categoryToStallMap[bi.name.toLowerCase()]) {
              categoryToStallMap[bi.name.toLowerCase()] = stallInfo;
            }
          });
        }

        // If this stall explicitly lists products, add them to map
        if (item.products) {
          item.products.forEach((p: any) => {
            if (!productToStallMap[p.id.toString()]) {
              productToStallMap[p.id.toString()] = stallInfo;
            }
          });
        }
        
        return {
          id: stallInfo.id,
          name: stallInfo.name,
          description: item.description || 'Our delicious stall',
          imageData: item.imageData?.trim() ? (item.imageData.trim().startsWith('data:') ? item.imageData.trim() : `data:image/png;base64,${item.imageData.trim()}`) : '',
          active: item.active,
          temporarilyClosed: item.temporarilyClosed
        };
      });

      // Map Products to FoodItems using the lookup map as fallback
      const mappedFoodItems: FoodItem[] = productsData.map((item: any) => {
        const rawImg = item.imageData?.trim();
        const finalImage = rawImg ? (rawImg.startsWith('data:') ? rawImg : `data:image/png;base64,${rawImg}`) : '';
        
        const itemId = item.id.toString();
        const stallFromBackend = item.stalls && item.stalls.length > 0 ? { id: item.stalls[0].id.toString(), name: item.stalls[0].name } : null;
        const stallFromMap = productToStallMap[itemId];
        const stallFromCategory = item.category ? categoryToStallMap[item.category.toLowerCase()] : null;
        
        return {
          id: itemId,
          name: item.name,
          description: item.description || 'No description available',
          price: item.price || item.basePrice || 0,
          category: item.category,
          image: finalImage,
          isVeg: item.veg,
          isPopular: item.active, 
          stock: item.stock,
          stallId: (stallFromBackend?.id || stallFromMap?.id || stallFromCategory?.id),
          stallName: (stallFromBackend?.name || stallFromMap?.name || stallFromCategory?.name)
        };
      });

      setCategories(mappedCategories);
      setFoodItems(mappedFoodItems);
      setStalls(mappedStalls);
    } catch (err: any) {
      setError(err.message);
      console.error('Error fetching food data:', err);
    } finally {
      setIsLoading(false);
    }
  };

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

  return (
    <FoodContext.Provider value={{ categories, foodItems, stalls, isLoading, error, refreshData: fetchData }}>
      {children}
    </FoodContext.Provider>
  );
};

export const useFood = () => {
  const context = useContext(FoodContext);
  if (context === undefined) {
    throw new Error('useFood must be used within a FoodProvider');
  }
  return context;
};
