import React, { createContext, useContext, useState, ReactNode } from 'react';
import { CollectionItem, JournalEntry } from '../../types';
import { COLLECTIONS, JOURNAL_ENTRIES } from '../../constants';

export interface CartItem extends CollectionItem {
    quantity: number;
}

export interface Order {
    id: number;
    customer_email: string;
    customer_name: string;
    shipping_address: any;
    items: any[];
    total_amount: number;
    payment_status: string;
    shipping_status: string;
    created_at: string;
}

interface StoreContextType {
    products: CollectionItem[];
    articles: JournalEntry[];
    cart: CartItem[];
    orders: Order[];
    isCartOpen: boolean;
    setCartOpen: (open: boolean) => void;
    addToCart: (product: CollectionItem) => void;
    removeFromCart: (productId: number) => void;
    updateQuantity: (productId: number, quantity: number) => void;
    clearCart: () => void;
    placeOrder: (orderData: Partial<Order>) => Promise<Order>;
    fetchOrders: () => Promise<void>;
    updateOrderStatus: (id: number, status: string) => Promise<void>;
    addProduct: (product: CollectionItem) => void;
    updateProduct: (product: CollectionItem) => void;
    deleteProduct: (id: number) => void;
    addArticle: (article: JournalEntry) => void;
    updateArticle: (article: JournalEntry) => void;
    deleteArticle: (id: number) => void;
}

const StoreContext = createContext<StoreContextType | undefined>(undefined);

const API_URL = 'http://localhost:5000/api';

export const StoreProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
    const [products, setProducts] = useState<CollectionItem[]>([]);
    const [articles, setArticles] = useState<JournalEntry[]>([]);
    const [orders, setOrders] = useState<Order[]>([]);
    const [cart, setCart] = useState<CartItem[]>([]);
    const [isCartOpen, setCartOpen] = useState(false);
    const [isLoading, setIsLoading] = useState(true);

    // Persist cart (minimal data only)
    React.useEffect(() => {
        try {
            const minimalCart = cart.map(item => ({ id: item.id, quantity: item.quantity }));
            localStorage.setItem('cart', JSON.stringify(minimalCart));
        } catch (err) {
            console.error('Failed to save cart to localStorage:', err);
        }
    }, [cart]);

    // Hydrate cart when products are loaded
    React.useEffect(() => {
        if (!isLoading && products.length > 0) {
            const saved = localStorage.getItem('cart');
            if (saved) {
                try {
                    const parsed = JSON.parse(saved);
                    // Handle both old format (full objects) and new format (minimal)
                    const hydrated = parsed.map((m: any) => {
                        const productId = typeof m === 'object' && m !== null ? (m.id || m.productId) : m;
                        const product = products.find(p => p.id === productId);
                        if (product) {
                            return { ...product, quantity: m.quantity || 1 };
                        }
                        return null;
                    }).filter(Boolean) as CartItem[];
                    setCart(hydrated);
                } catch (err) {
                    console.error('Failed to hydrate cart:', err);
                }
            }
        }
    }, [isLoading, products]);

    // Initial Fetch
    React.useEffect(() => {
        const fetchData = async () => {
            try {
                const [prodRes, artRes] = await Promise.all([
                    fetch(`${API_URL}/products`),
                    fetch(`${API_URL}/articles`)
                ]);
                const prods = await prodRes.json();
                const arts = await artRes.json();
                setProducts(prods);
                setArticles(arts);
            } catch (err) {
                console.error('Failed to fetch data from backend, falling back to static data', err);
                setProducts(COLLECTIONS);
                setArticles(JOURNAL_ENTRIES);
            } finally {
                setIsLoading(false);
            }
        };
        fetchData();
    }, []);

    // Cart Actions
    const addToCart = (product: CollectionItem) => {
        setCart(prev => {
            const existing = prev.find(item => item.id === product.id);
            if (existing) {
                return prev.map(item =>
                    item.id === product.id ? { ...item, quantity: item.quantity + 1 } : item
                );
            }
            return [...prev, { ...product, quantity: 1 }];
        });
        setCartOpen(true);
    };

    const removeFromCart = (productId: number) => {
        setCart(prev => prev.filter(item => item.id !== productId));
    };

    const updateQuantity = (productId: number, quantity: number) => {
        if (quantity < 1) {
            removeFromCart(productId);
            return;
        }
        setCart(prev => prev.map(item =>
            item.id === productId ? { ...item, quantity } : item
        ));
    };

    const clearCart = () => setCart([]);

    // Order Actions
    const fetchOrders = async () => {
        try {
            const res = await fetch(`${API_URL}/orders`);
            const data = await res.json();
            setOrders(data);
        } catch (err) {
            console.error('Failed to fetch orders:', err);
        }
    };

    const placeOrder = async (orderData: Partial<Order>) => {
        try {
            const res = await fetch(`${API_URL}/orders`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(orderData)
            });
            const newOrder = await res.json();
            setOrders(prev => [newOrder, ...prev]);
            return newOrder;
        } catch (err) {
            console.error('Failed to place order:', err);
            throw err;
        }
    };

    const updateOrderStatus = async (id: number, status: string) => {
        try {
            const res = await fetch(`${API_URL}/orders/${id}/status`, {
                method: 'PUT',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ shipping_status: status })
            });
            const updatedOrder = await res.json();
            setOrders(prev => prev.map(o => o.id === id ? updatedOrder : o));
        } catch (err) {
            console.error('Failed to update order status:', err);
        }
    };

    const addProduct = async (product: CollectionItem) => {
        try {
            const res = await fetch(`${API_URL}/products`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(product)
            });
            const newProduct = await res.json();
            setProducts(prev => [...prev, newProduct]);
        } catch (err) {
            console.error('Failed to add product:', err);
        }
    };

    const updateProduct = async (updatedProduct: CollectionItem) => {
        try {
            const res = await fetch(`${API_URL}/products/${updatedProduct.id}`, {
                method: 'PUT',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(updatedProduct)
            });
            const data = await res.json();
            setProducts(prev => prev.map(p => p.id === data.id ? data : p));
        } catch (err) {
            console.error('Failed to update product:', err);
        }
    };

    const deleteProduct = async (id: number) => {
        try {
            await fetch(`${API_URL}/products/${id}`, { method: 'DELETE' });
            setProducts(prev => prev.filter(p => p.id !== id));
        } catch (err) {
            console.error('Failed to delete product:', err);
        }
    };

    const addArticle = async (article: JournalEntry) => {
        try {
            const res = await fetch(`${API_URL}/articles`, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(article)
            });
            const newArticle = await res.json();
            setArticles(prev => [...prev, newArticle]);
        } catch (err) {
            console.error('Failed to add article:', err);
        }
    };

    const updateArticle = async (updatedArticle: JournalEntry) => {
        try {
            const res = await fetch(`${API_URL}/articles/${updatedArticle.id}`, {
                method: 'PUT',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(updatedArticle)
            });
            const data = await res.json();

            // If the updated article is featured, we must ensure only this one is featured in our local state
            if (data.isFeatured) {
                setArticles(prev => prev.map(a => ({
                    ...a,
                    isFeatured: a.id === data.id
                })));
            } else {
                setArticles(prev => prev.map(a => a.id === data.id ? data : a));
            }
        } catch (err) {
            console.error('Failed to update article:', err);
        }
    };

    const deleteArticle = async (id: number) => {
        try {
            await fetch(`${API_URL}/articles/${id}`, { method: 'DELETE' });
            setArticles(prev => prev.filter(a => a.id !== id));
        } catch (err) {
            console.error('Failed to delete article:', err);
        }
    };

    return (
        <StoreContext.Provider value={{
            products,
            articles,
            cart,
            orders,
            isCartOpen,
            setCartOpen,
            addToCart,
            removeFromCart,
            updateQuantity,
            clearCart,
            placeOrder,
            fetchOrders,
            updateOrderStatus,
            addProduct,
            updateProduct,
            deleteProduct,
            addArticle,
            updateArticle,
            deleteArticle
        }}>
            {isLoading ? <div className="fixed inset-0 bg-white z-50 flex items-center justify-center font-display text-xl animate-pulse">Loading Store...</div> : children}
        </StoreContext.Provider>
    );
};

export const useStore = () => {
    const context = useContext(StoreContext);
    if (context === undefined) {
        throw new Error('useStore must be used within a StoreProvider');
    }
    return context;
};
