import React, { useState, useEffect, useCallback } from 'react';
import { Shop, Product, ShoppingEventCreate, ProductInEvent, ShoppingEvent, BrandInShop } from '../types';
import { shopApi, productApi, shoppingEventApi, brandInShopApi } from '../services/api';
import { useBodyScrollLock } from '../hooks/useBodyScrollLock';

interface AddShoppingEventModalProps {
  isOpen: boolean;
  onClose: () => void;
  onEventAdded: () => void;
  editEvent?: ShoppingEvent | null;
}

const AddShoppingEventModal: React.FC<AddShoppingEventModalProps> = ({ 
  isOpen, 
  onClose, 
  onEventAdded, 
  editEvent 
}) => {
  // Use body scroll lock when modal is open
  useBodyScrollLock(isOpen);

  const [shops, setShops] = useState<Shop[]>([]);
  const [products, setProducts] = useState<Product[]>([]);
  const [shopBrands, setShopBrands] = useState<BrandInShop[]>([]);
  const [loading, setLoading] = useState(false);
  const [message, setMessage] = useState('');
  
  const isEditMode = Boolean(editEvent);
  
  const [formData, setFormData] = useState<ShoppingEventCreate>({
    shop_id: 0,
    date: new Date().toISOString().split('T')[0],
    total_amount: undefined,
    notes: '',
    products: []
  });

  const [selectedProducts, setSelectedProducts] = useState<ProductInEvent[]>([]);
  const [newProductItem, setNewProductItem] = useState<ProductInEvent>({
    product_id: 0,
    amount: 1,
    price: 0,
    discount: false
  });
  const [autoCalculate, setAutoCalculate] = useState<boolean>(true);

  // Calculate total amount from selected products
  const calculateTotal = (products: ProductInEvent[]): number => {
    const total = products.reduce((total, item) => total + (item.amount * item.price), 0);
    return Math.round(total * 100) / 100; // Round to 2 decimal places to avoid floating-point errors
  };

  const loadEventData = useCallback(() => {
    if (editEvent) {
      // Use the date directly if it's already in YYYY-MM-DD format, otherwise format it
      let formattedDate = editEvent.date;
      if (editEvent.date.includes('T') || editEvent.date.length > 10) {
        // If the date includes time or is longer than YYYY-MM-DD, extract just the date part
        formattedDate = editEvent.date.split('T')[0];
      }
      
      // Map products to the format we need
      const mappedProducts = editEvent.products.map(p => ({
        product_id: p.id,
        amount: p.amount,
        price: p.price,
        discount: p.discount
      }));
      
      // Calculate the sum of all products
      const calculatedTotal = calculateTotal(mappedProducts);
      
      // Check if existing total matches calculated total (with small tolerance for floating point)
      const existingTotal = editEvent.total_amount || 0;
      const totalMatches = Math.abs(existingTotal - calculatedTotal) < 0.01;
      
      setFormData({
        shop_id: editEvent.shop.id,
        date: formattedDate,
        total_amount: editEvent.total_amount,
        notes: editEvent.notes || '',
        products: []
      });
      
      setSelectedProducts(mappedProducts);
      setAutoCalculate(totalMatches); // Enable auto-calc if totals match, disable if they don't
    } else {
      // Reset form for adding new event
      setFormData({
        shop_id: 0,
        date: new Date().toISOString().split('T')[0],
        total_amount: undefined,
        notes: '',
        products: []
      });
      setSelectedProducts([]);
      setAutoCalculate(true);
    }
    setMessage('');
  }, [editEvent]);

  useEffect(() => {
    if (isOpen) {
      fetchShops();
      fetchProducts();
      loadEventData();
    }
  }, [isOpen, loadEventData]);

  const handleSubmit = useCallback(async (e: React.FormEvent) => {
    e.preventDefault();
    setLoading(true);
    setMessage('');

    try {
      const eventData = {
        ...formData,
        products: selectedProducts
      };

      if (isEditMode && editEvent) {
        await shoppingEventApi.update(editEvent.id, eventData);
        setMessage('Shopping event updated successfully!');
      } else {
        await shoppingEventApi.create(eventData);
        setMessage('Shopping event created successfully!');
      }
      
      setTimeout(() => {
        onEventAdded();
        onClose();
      }, 1500);
    } catch (error) {
      console.error('Error saving shopping event:', error);
      setMessage(`Error ${isEditMode ? 'updating' : 'creating'} shopping event. Please try again.`);
      setTimeout(() => setMessage(''), 3000);
    } finally {
      setLoading(false);
    }
  }, [formData, selectedProducts, isEditMode, editEvent, onEventAdded, onClose]);

  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (!isOpen) return;
      
      if (event.key === 'Escape') {
        onClose();
      } else if (event.key === 'Enter' && !event.shiftKey && !loading) {
        // Only trigger submit if not in a textarea and form is valid
        const target = event.target as HTMLElement;
        if (target.tagName !== 'TEXTAREA') {
          event.preventDefault();
          if (formData.shop_id > 0 && selectedProducts.length > 0) {
            handleSubmit(event as any);
          }
        }
      }
    };

    if (isOpen) {
      document.addEventListener('keydown', handleKeyDown);
    }
    
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [isOpen, formData, selectedProducts, loading, onClose, handleSubmit]);

  // Update total amount whenever selectedProducts changes
  useEffect(() => {
    if (autoCalculate) {
      const calculatedTotal = calculateTotal(selectedProducts);
      setFormData(prev => ({
        ...prev,
        total_amount: calculatedTotal > 0 ? calculatedTotal : undefined
      }));
    }
  }, [selectedProducts, autoCalculate]);

  const fetchShops = async () => {
    try {
      const response = await shopApi.getAll();
      setShops(response.data);
    } catch (error) {
      console.error('Error fetching shops:', error);
      setMessage('Error loading shops. Please try again.');
      setTimeout(() => setMessage(''), 3000);
    }
  };

  const fetchProducts = async () => {
    try {
      // If we have a shopping date, get products available for that date
      // Otherwise, get all non-deleted products
      const response = formData.date 
        ? await productApi.getAvailableForShopping(formData.date)
        : await productApi.getAll(false); // false = don't show deleted
      setProducts(response.data);
    } catch (error) {
      console.error('Error fetching products:', error);
      setMessage('Error loading products. Please try again.');
      setTimeout(() => setMessage(''), 3000);
    }
  };

  const fetchShopBrands = async (shopId: number) => {
    if (shopId === 0) {
      setShopBrands([]);
      return;
    }
    
    try {
      const response = await brandInShopApi.getByShop(shopId);
      setShopBrands(response.data);
    } catch (error) {
      console.error('Error fetching shop brands:', error);
      setShopBrands([]);
    }
  };

  // Effect to load shop brands when shop selection changes
  useEffect(() => {
    if (formData.shop_id > 0) {
      fetchShopBrands(formData.shop_id);
    } else {
      setShopBrands([]);
    }
  }, [formData.shop_id]);

  // Effect to refetch products when shopping date changes
  useEffect(() => {
    if (isOpen && formData.date) {
      fetchProducts();
    }
  }, [formData.date, isOpen]);

  const addProductToEvent = () => {
    if (newProductItem.product_id > 0 && newProductItem.amount > 0 && newProductItem.price >= 0) {
      setSelectedProducts([...selectedProducts, { ...newProductItem }]);
      setNewProductItem({ product_id: 0, amount: 1, price: 0, discount: false });
    }
  };

  const removeProductFromEvent = (index: number) => {
    setSelectedProducts(selectedProducts.filter((_, i) => i !== index));
  };

  const editProductFromEvent = (index: number) => {
    const productToEdit = selectedProducts[index];
    // Load the product data into the input fields
    setNewProductItem({
      product_id: productToEdit.product_id,
      amount: productToEdit.amount,
      price: productToEdit.price,
      discount: productToEdit.discount
    });
    // Remove the item from the selected list
    setSelectedProducts(selectedProducts.filter((_, i) => i !== index));
  };

  const getProductName = (id: number) => {
    const product = products.find(p => p.id === id);
    if (!product) return 'Unknown';
    
    const weightInfo = product.weight ? `${product.weight}${product.weight_unit}` : product.weight_unit;
    const organicEmoji = product.organic ? ' 🌱' : '';
    const brandInfo = product.brand ? ` (${product.brand.name})` : '';
    return `${product.name}${organicEmoji} ${weightInfo}${brandInfo}`;
  };

  // Filter products based on selected shop's brands
  const getFilteredProducts = () => {
    // If no shop is selected or shop has no brands, show all products
    if (formData.shop_id === 0 || shopBrands.length === 0) {
      return products;
    }
    
    // Get brand IDs available in the selected shop
    const availableBrandIds = shopBrands.map(sb => sb.brand_id);
    
    // Filter products to only show those with brands available in the shop
    // Also include products without brands (brand_id is null/undefined)
    return products.filter(product => 
      !product.brand_id || availableBrandIds.includes(product.brand_id)
    );
  };

  if (!isOpen) return null;

  return (
    <div 
      className="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full z-50"
      onClick={(e) => {
        // Close modal if clicking on backdrop
        if (e.target === e.currentTarget) {
          onClose();
        }
      }}
    >
      <div 
        className="relative min-h-screen md:min-h-0 md:top-10 mx-auto p-4 md:p-5 w-full md:max-w-4xl md:shadow-lg md:rounded-md bg-white"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="mt-3">
          <div className="flex justify-between items-center mb-4">
            <h3 className="text-lg md:text-xl font-medium text-gray-900">
              {isEditMode ? 'Edit Shopping Event' : 'Add New Shopping Event'}
            </h3>
            <button
              onClick={onClose}
              className="text-gray-400 hover:text-gray-600 p-2"
            >
              <svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
              </svg>
            </button>
          </div>

          {message && (
            <div className={`mb-4 px-4 py-3 rounded ${
              message.includes('Error') 
                ? 'bg-red-50 border border-red-200 text-red-700' 
                : 'bg-green-50 border border-green-200 text-green-700'
            }`}>
              {message}
            </div>
          )}

          <form onSubmit={handleSubmit} className="space-y-6">
            {/* Shop and Date Selection */}
            <div className="flex flex-col md:flex-row md:space-x-4 space-y-4 md:space-y-0">
              <div className="flex-1">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Shop
                </label>
                <select
                  value={formData.shop_id}
                  onChange={(e) => setFormData({...formData, shop_id: parseInt(e.target.value)})}
                  className="w-full h-12 md:h-10 border border-gray-300 rounded-md px-3 py-2 text-base md:text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
                  required
                >
                  <option value={0}>Select a shop</option>
                  {shops.map(shop => (
                    <option key={shop.id} value={shop.id}>
                      {shop.name} - {shop.city}
                    </option>
                  ))}
                </select>
              </div>
              <div className="w-full md:w-48">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Date
                </label>
                <input
                  type="date"
                  value={formData.date}
                  onChange={(e) => setFormData({...formData, date: e.target.value})}
                  className="w-full h-12 md:h-10 border border-gray-300 rounded-md px-3 py-2 text-base md:text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
                  required
                />
              </div>
            </div>

            {/* Add Products Section */}
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-2">
                Add Products
              </label>
              
              {/* Mobile Product Form - Stacked */}
              <div className="md:hidden space-y-4 mb-4">
                <div>
                  <label className="block text-sm font-medium text-gray-700 mb-1">
                    Product
                  </label>
                  <select
                    value={newProductItem.product_id}
                    onChange={(e) => setNewProductItem({...newProductItem, product_id: parseInt(e.target.value)})}
                    className="w-full h-12 border border-gray-300 rounded-md px-3 py-2 text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
                  >
                    <option value={0}>Select a product</option>
                    {Object.entries(
                      getFilteredProducts().reduce((groups, product) => {
                        const category = product.category.name;
                        if (!groups[category]) {
                          groups[category] = [];
                        }
                        groups[category].push(product);
                        return groups;
                      }, {} as Record<string, typeof products>)
                    )
                    .sort(([a], [b]) => a.localeCompare(b))
                    .map(([category, categoryProducts]) => (
                      <optgroup key={category} label={category}>
                        {categoryProducts
                          .sort((a, b) => a.name.localeCompare(b.name))
                          .map(product => (
                            <option key={product.id} value={product.id}>
                              {product.name}{product.organic ? ' 🌱' : ''}{product.weight ? ` ${product.weight}${product.weight_unit}` : product.weight_unit}{product.brand ? ` (${product.brand.name})` : ''}
                            </option>
                          ))
                        }
                      </optgroup>
                    ))}
                  </select>
                </div>
                
                <div className="grid grid-cols-2 gap-4">
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-1">
                      Amount
                    </label>
                    <input
                      type="number"
                      step="1"
                      min="1"
                      placeholder="1"
                      value={newProductItem.amount}
                      onChange={(e) => setNewProductItem({...newProductItem, amount: parseFloat(e.target.value)})}
                      className="w-full h-12 border border-gray-300 rounded-md px-3 py-2 text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
                    />
                  </div>
                  <div>
                    <label className="block text-sm font-medium text-gray-700 mb-1">
                      Price ($)
                    </label>
                    <input
                      type="number"
                      step="0.01"
                      min="0"
                      placeholder="0.00"
                      value={newProductItem.price}
                      onChange={(e) => setNewProductItem({...newProductItem, price: parseFloat(e.target.value)})}
                      className="w-full h-12 border border-gray-300 rounded-md px-3 py-2 text-base focus:outline-none focus:ring-2 focus:ring-blue-500"
                    />
                  </div>
                </div>
                
                <div className="flex items-center justify-between">
                  <label className="flex items-center space-x-2">
                    <input
                      type="checkbox"
                      checked={newProductItem.discount}
                      onChange={(e) => setNewProductItem({...newProductItem, discount: e.target.checked})}
                      className="h-5 w-5 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
                    />
                    <span className="text-sm font-medium text-gray-700">Discount</span>
                  </label>
                  
                  <button
                    type="button"
                    onClick={addProductToEvent}
                    className="px-6 py-3 bg-green-500 hover:bg-green-700 text-white rounded-md font-medium text-base"
                  >
                    Add Product
                  </button>
                </div>
              </div>

              {/* Desktop Product Form - Horizontal */}
              <div className="hidden md:flex space-x-2 mb-4">
                <div className="flex-1">
                  <label className="block text-xs font-medium text-gray-700 mb-1">
                    Product
                  </label>
                  <select
                    value={newProductItem.product_id}
                    onChange={(e) => setNewProductItem({...newProductItem, product_id: parseInt(e.target.value)})}
                    className="w-full h-10 border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
                  >
                    <option value={0}>Select a product</option>
                    {Object.entries(
                      getFilteredProducts().reduce((groups, product) => {
                        const category = product.category.name;
                        if (!groups[category]) {
                          groups[category] = [];
                        }
                        groups[category].push(product);
                        return groups;
                      }, {} as Record<string, typeof products>)
                    )
                    .sort(([a], [b]) => a.localeCompare(b))
                    .map(([category, categoryProducts]) => (
                      <optgroup key={category} label={category}>
                        {categoryProducts
                          .sort((a, b) => a.name.localeCompare(b.name))
                          .map(product => (
                            <option key={product.id} value={product.id}>
                              {product.name}{product.organic ? ' 🌱' : ''}{product.weight ? ` ${product.weight}${product.weight_unit}` : product.weight_unit}{product.brand ? ` (${product.brand.name})` : ''}
                            </option>
                          ))
                        }
                      </optgroup>
                    ))}
                  </select>
                </div>
                <div>
                  <label className="block text-xs font-medium text-gray-700 mb-1">
                    Amount
                  </label>
                  <input
                    type="number"
                    step="1"
                    min="1"
                    placeholder="1"
                    value={newProductItem.amount}
                    onChange={(e) => setNewProductItem({...newProductItem, amount: parseFloat(e.target.value)})}
                    className="w-24 h-10 border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
                  />
                </div>
                <div>
                  <label className="block text-xs font-medium text-gray-700 mb-1">
                    Price ($)
                  </label>
                  <input
                    type="number"
                    step="0.01"
                    min="0"
                    placeholder="0.00"
                    value={newProductItem.price}
                    onChange={(e) => setNewProductItem({...newProductItem, price: parseFloat(e.target.value)})}
                    className="w-24 h-10 border border-gray-300 rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-blue-500"
                  />
                </div>
                <div className="flex items-center">
                  <label className="flex items-center space-x-2">
                    <input
                      type="checkbox"
                      checked={newProductItem.discount}
                      onChange={(e) => setNewProductItem({...newProductItem, discount: e.target.checked})}
                      className="h-5 w-5 text-blue-600 focus:ring-blue-500 border-gray-300 rounded"
                    />
                    <span className="text-xs font-medium text-gray-700">Discount</span>
                  </label>
                </div>
                <div className="flex items-end">
                  <button
                    type="button"
                    onClick={addProductToEvent}
                    className="px-6 py-2 bg-green-500 hover:bg-green-700 text-white rounded-md font-medium text-sm"
                  >
                    Add Product
                  </button>
                </div>
              </div>

              {/* Selected Products List */}
              <div className="overflow-x-auto">
                <table className="min-w-full divide-y divide-gray-200">
                  <thead className="bg-gray-50">
                    <tr>
                      <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                        Product
                      </th>
                      <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                        Amount
                      </th>
                      <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                        Price ($)
                      </th>
                      <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                        Discount
                      </th>
                      <th scope="col" className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
                        Total ($)
                      </th>
                      <th scope="col" className="relative px-6 py-3">
                        <span className="sr-only">Edit</span>
                      </th>
                    </tr>
                  </thead>
                  <tbody className="bg-white divide-y divide-gray-200">
                    {selectedProducts.map((product, index) => (
                      <tr key={index}>
                        <td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
                          {getProductName(product.product_id)}
                        </td>
                        <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                          {product.amount}
                        </td>
                        <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                          {product.price.toFixed(2)}
                        </td>
                        <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                          {product.discount ? 'Yes' : 'No'}
                        </td>
                        <td className="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
                          {(product.amount * product.price).toFixed(2)}
                        </td>
                        <td className="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
                          <button
                            type="button"
                            onClick={() => editProductFromEvent(index)}
                            className="text-indigo-600 hover:text-indigo-900 mr-2"
                          >
                            Edit
                          </button>
                          <button
                            type="button"
                            onClick={() => removeProductFromEvent(index)}
                            className="text-red-600 hover:text-red-900"
                          >
                            Remove
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </div>

            {/* Total Amount and Notes */}
            <div className="flex flex-col md:flex-row md:space-x-4 space-y-4 md:space-y-0">
              <div className="flex-1">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Total Amount ($)
                </label>
                <input
                  type="number"
                  step="0.01"
                  min="0"
                  placeholder="0.00"
                  value={formData.total_amount}
                  onChange={(e) => setFormData({...formData, total_amount: parseFloat(e.target.value)})}
                  className="w-full h-12 md:h-10 border border-gray-300 rounded-md px-3 py-2 text-base md:text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
                />
              </div>
              <div className="flex-1">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Notes
                </label>
                <textarea
                  value={formData.notes}
                  onChange={(e) => setFormData({...formData, notes: e.target.value})}
                  className="w-full h-24 md:h-10 border border-gray-300 rounded-md px-3 py-2 text-base md:text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
                />
              </div>
            </div>

            {/* Save Button */}
            <div className="flex justify-end">
              <button
                type="submit"
                disabled={loading}
                className="px-6 py-3 bg-blue-500 hover:bg-blue-700 text-white rounded-md font-medium text-base disabled:opacity-50"
              >
                {loading ? 'Saving...' : 'Save'}
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>
  );
};

export default AddShoppingEventModal;