import { useCallback, useContext, useEffect, useMemo, useState } from "react";
import {
  addItem,
  getClassification,
  getItemByName,
  getList,
  getRecentlyBought,
  getSuggestions,
  markBought,
  updateItemImage,
  updateItemWithClassification
} from "../api/list";
import FloatingActionButton from "../components/common/FloatingActionButton";
import SortDropdown from "../components/common/SortDropdown";
import AddItemForm from "../components/forms/AddItemForm";
import GroceryListItem from "../components/items/GroceryListItem";
import AddItemWithDetailsModal from "../components/modals/AddItemWithDetailsModal";
import ConfirmAddExistingModal from "../components/modals/ConfirmAddExistingModal";
import EditItemModal from "../components/modals/EditItemModal";
import SimilarItemModal from "../components/modals/SimilarItemModal";
import StoreTabs from "../components/store/StoreTabs";
import { ZONE_FLOW } from "../constants/classifications";
import { ROLES } from "../constants/roles";
import { AuthContext } from "../context/AuthContext";
import { HouseholdContext } from "../context/HouseholdContext";
import { SettingsContext } from "../context/SettingsContext";
import { StoreContext } from "../context/StoreContext";
import "../styles/pages/GroceryList.css";
import { findSimilarItems } from "../utils/stringSimilarity";


export default function GroceryList() {
  const { role } = useContext(AuthContext);
  const { activeHousehold } = useContext(HouseholdContext);
  const { activeStore } = useContext(StoreContext);
  const { settings } = useContext(SettingsContext);

  // === State === //
  const [items, setItems] = useState([]);
  const [recentlyBoughtItems, setRecentlyBoughtItems] = useState([]);
  const [recentlyBoughtDisplayCount, setRecentlyBoughtDisplayCount] = useState(settings.recentlyBoughtCount);
  const [sortMode, setSortMode] = useState(settings.defaultSortMode);
  const [suggestions, setSuggestions] = useState([]);
  const [showAddForm, setShowAddForm] = useState(true);
  const [loading, setLoading] = useState(true);
  const [buttonText, setButtonText] = useState("Add Item");
  const [pendingItem, setPendingItem] = useState(null);
  const [showAddDetailsModal, setShowAddDetailsModal] = useState(false);
  const [showSimilarModal, setShowSimilarModal] = useState(false);
  const [similarItemSuggestion, setSimilarItemSuggestion] = useState(null);
  const [showEditModal, setShowEditModal] = useState(false);
  const [editingItem, setEditingItem] = useState(null);
  const [recentlyBoughtCollapsed, setRecentlyBoughtCollapsed] = useState(settings.recentlyBoughtCollapsed);
  const [collapsedZones, setCollapsedZones] = useState({});
  const [showConfirmAddExisting, setShowConfirmAddExisting] = useState(false);
  const [confirmAddExistingData, setConfirmAddExistingData] = useState(null);


  // === Data Loading ===
  const loadItems = async () => {
    if (!activeHousehold?.id || !activeStore?.id) {
      setLoading(false);
      return;
    }

    setLoading(true);
    try {
      const res = await getList(activeHousehold.id, activeStore.id);
      console.log('[GroceryList] Items loaded:', res.data);
      setItems(res.data.items || res.data || []);
    } catch (error) {
      console.error('[GroceryList] Failed to load items:', error);
      setItems([]);
    } finally {
      setLoading(false);
    }
  };


  const loadRecentlyBought = async () => {
    if (!activeHousehold?.id || !activeStore?.id) return;
    try {
      const res = await getRecentlyBought(activeHousehold.id, activeStore.id);
      setRecentlyBoughtItems(res.data);
    } catch (error) {
      console.error("Failed to load recently bought items:", error);
      setRecentlyBoughtItems([]);
    }
  };


  useEffect(() => {
    loadItems();
    loadRecentlyBought();
  }, [activeHousehold?.id, activeStore?.id]);


  // === Zone Collapse Handler ===
  const toggleZoneCollapse = (zone) => {
    setCollapsedZones(prev => ({
      ...prev,
      [zone]: !prev[zone]
    }));
  };

  // === Sorted Items Computation ===
  const sortedItems = useMemo(() => {
    const sorted = [...items];

    if (sortMode === "az") sorted.sort((a, b) => a.item_name.localeCompare(b.item_name));
    if (sortMode === "za") sorted.sort((a, b) => b.item_name.localeCompare(a.item_name));
    if (sortMode === "qty-high") sorted.sort((a, b) => b.quantity - a.quantity);
    if (sortMode === "qty-low") sorted.sort((a, b) => a.quantity - b.quantity);
    if (sortMode === "zone") {
      sorted.sort((a, b) => {
        // Items without classification go to the end
        if (!a.zone && b.zone) return 1;
        if (a.zone && !b.zone) return -1;
        if (!a.zone && !b.zone) return a.item_name.localeCompare(b.item_name);

        // Sort by ZONE_FLOW order
        const aZoneIndex = ZONE_FLOW.indexOf(a.zone);
        const bZoneIndex = ZONE_FLOW.indexOf(b.zone);

        // If zone not in ZONE_FLOW, put at end
        const aIndex = aZoneIndex === -1 ? ZONE_FLOW.length : aZoneIndex;
        const bIndex = bZoneIndex === -1 ? ZONE_FLOW.length : bZoneIndex;

        const zoneCompare = aIndex - bIndex;
        if (zoneCompare !== 0) return zoneCompare;

        // Then by item_type
        const typeCompare = (a.item_type || "").localeCompare(b.item_type || "");
        if (typeCompare !== 0) return typeCompare;

        // Then by item_group
        const groupCompare = (a.item_group || "").localeCompare(b.item_group || "");
        if (groupCompare !== 0) return groupCompare;

        // Finally by name
        return a.item_name.localeCompare(b.item_name);
      });
    }

    return sorted;
  }, [items, sortMode]);


  // === Suggestion Handler ===
  const handleSuggest = async (text) => {
    if (!text.trim()) {
      setSuggestions([]);
      setButtonText("Add Item");
      return;
    }

    if (!activeHousehold?.id || !activeStore?.id) {
      setSuggestions([]);
      setButtonText("Create + Add");
      return;
    }

    const lowerText = text.toLowerCase().trim();

    try {
      const response = await getSuggestions(activeHousehold.id, activeStore.id, text);
      const suggestionList = response.data.map(s => s.item_name);
      setSuggestions(suggestionList);

      // All suggestions are now lowercase from DB, direct comparison
      const exactMatch = suggestionList.includes(lowerText);
      setButtonText(exactMatch ? "Add" : "Create + Add");
    } catch {
      setSuggestions([]);
      setButtonText("Create + Add");
    }
  };


  // === Item Addition Handlers ===
  const handleAdd = useCallback(async (itemName, quantity) => {
    if (!itemName.trim()) return;
    if (!activeHousehold?.id || !activeStore?.id) return;

    // Check if item already exists
    let existingItem = null;
    try {
      const response = await getItemByName(activeHousehold.id, activeStore.id, itemName);
      existingItem = response.data;
    } catch {
      // Item doesn't exist, continue
    }

    if (existingItem) {
      await processItemAddition(itemName, quantity);
      return;
    }

    setItems(prevItems => {
      const allItems = [...prevItems, ...recentlyBoughtItems];
      const similar = findSimilarItems(itemName, allItems, 70);
      if (similar.length > 0) {
        setSimilarItemSuggestion({ originalName: itemName, suggestedItem: similar[0], quantity });
        setShowSimilarModal(true);
        return prevItems;
      }

      processItemAddition(itemName, quantity);
      return prevItems;
    });
  }, [activeHousehold?.id, activeStore?.id, recentlyBoughtItems]);


  const processItemAddition = useCallback(async (itemName, quantity) => {
    if (!activeHousehold?.id || !activeStore?.id) return;

    // Fetch current item state from backend
    let existingItem = null;
    try {
      const response = await getItemByName(activeHousehold.id, activeStore.id, itemName);
      existingItem = response.data;
    } catch {
      // Item doesn't exist, continue with add
    }

    if (existingItem?.bought === false) {
      const currentQuantity = existingItem.quantity;
      const newQuantity = currentQuantity + quantity;

      // Show modal instead of window.confirm
      setConfirmAddExistingData({
        itemName,
        currentQuantity,
        addingQuantity: quantity,
        newQuantity,
        existingItem
      });
      setShowConfirmAddExisting(true);
    } else if (existingItem) {
      await addItem(activeHousehold.id, activeStore.id, itemName, quantity, null);
      setSuggestions([]);
      setButtonText("Add Item");

      // Reload lists to reflect the changes
      await loadItems();
      await loadRecentlyBought();
    } else {
      setPendingItem({ itemName, quantity });
      setShowAddDetailsModal(true);
    }
  }, [activeHousehold?.id, activeStore?.id, items, loadItems]);


  // === Similar Item Modal Handlers ===
  const handleSimilarCancel = useCallback(() => {
    setShowSimilarModal(false);
    setSimilarItemSuggestion(null);
  }, []);


  const handleSimilarNo = useCallback(async () => {
    if (!similarItemSuggestion) return;
    setShowSimilarModal(false);
    await processItemAddition(similarItemSuggestion.originalName, similarItemSuggestion.quantity);
    setSimilarItemSuggestion(null);
  }, [similarItemSuggestion, processItemAddition]);


  const handleSimilarYes = useCallback(async () => {
    if (!similarItemSuggestion) return;
    setShowSimilarModal(false);
    await processItemAddition(similarItemSuggestion.suggestedItem.item_name, similarItemSuggestion.quantity);
    setSimilarItemSuggestion(null);
  }, [similarItemSuggestion, processItemAddition]);


  // === Confirm Add Existing Modal Handlers ===
  const handleConfirmAddExisting = useCallback(async () => {
    if (!confirmAddExistingData) return;
    if (!activeHousehold?.id || !activeStore?.id) return;

    const { itemName, newQuantity, existingItem } = confirmAddExistingData;

    setShowConfirmAddExisting(false);
    setConfirmAddExistingData(null);

    try {
      await addItem(activeHousehold.id, activeStore.id, itemName, newQuantity, null);

      const response = await getItemByName(activeHousehold.id, activeStore.id, itemName);
      const updatedItem = response.data;

      setItems(prevItems =>
        prevItems.map(item =>
          item.id === existingItem.id ? updatedItem : item
        )
      );

      setSuggestions([]);
      setButtonText("Add Item");
    } catch (error) {
      console.error("Failed to update item:", error);
      await loadItems();
    }
  }, []);


  // === Add Details Modal Handlers ===
  const handleAddWithDetails = useCallback(async (imageFile, classification) => {
    if (!pendingItem) return;
    if (!activeHousehold?.id || !activeStore?.id) return;

    try {
      await addItem(activeHousehold.id, activeStore.id, pendingItem.itemName, pendingItem.quantity, imageFile);

      if (classification) {
        // Apply classification if provided
        await updateItemWithClassification(activeHousehold.id, activeStore.id, pendingItem.itemName, pendingItem.quantity, classification);
      }

      // Fetch the newly added item
      const itemResponse = await getItemByName(activeHousehold.id, activeStore.id, pendingItem.itemName);
      const newItem = itemResponse.data;

      setShowAddDetailsModal(false);
      setPendingItem(null);
      setSuggestions([]);
      setButtonText("Add Item");

      // Add to state
      if (newItem) {
        setItems(prevItems => [...prevItems, newItem]);
      }
    } catch (error) {
      console.error("Failed to add item:", error);
      alert("Failed to add item. Please try again.");
    }
  }, [activeHousehold?.id, activeStore?.id, pendingItem]);

  const handleAddDetailsSkip = useCallback(async () => {
    if (!pendingItem) return;
    if (!activeHousehold?.id || !activeStore?.id) return;

    try {
      await addItem(activeHousehold.id, activeStore.id, pendingItem.itemName, pendingItem.quantity, null);

      // Fetch the newly added item
      const itemResponse = await getItemByName(activeHousehold.id, activeStore.id, pendingItem.itemName);
      const newItem = itemResponse.data;

      setShowAddDetailsModal(false);
      setPendingItem(null);
      setSuggestions([]);
      setButtonText("Add Item");

      if (newItem) {
        setItems(prevItems => [...prevItems, newItem]);
      }
    } catch (error) {
      console.error("Failed to add item:", error);
      alert("Failed to add item. Please try again.");
    }
  }, [activeHousehold?.id, activeStore?.id, pendingItem]);


  const handleAddDetailsCancel = useCallback(() => {
    setShowAddDetailsModal(false);
    setPendingItem(null);
    setSuggestions([]);
    setButtonText("Add Item");
  }, []);


  // === Item Action Handlers ===
  const handleBought = useCallback(async (id, quantity) => {
    if (!activeHousehold?.id || !activeStore?.id) return;

    const item = items.find(i => i.id === id);
    if (!item) return;

    await markBought(activeHousehold.id, activeStore.id, item.item_name, quantity, true);

    // If buying full quantity, remove from list
    if (quantity >= item.quantity) {
      setItems(prevItems => prevItems.filter(item => item.id !== id));
    } else {
      // If partial, fetch updated item
      const response = await getItemByName(activeHousehold.id, activeStore.id, item.item_name);
      const updatedItem = response.data;

      setItems(prevItems =>
        prevItems.map(i => i.id === id ? updatedItem : i)
      );
    }

    loadRecentlyBought();
  }, [activeHousehold?.id, activeStore?.id, items]);

  const handleImageAdded = useCallback(async (id, itemName, quantity, imageFile) => {
    if (!activeHousehold?.id || !activeStore?.id) return;

    try {
      const response = await updateItemImage(activeHousehold.id, activeStore.id, id, itemName, quantity, imageFile);

      setItems(prevItems =>
        prevItems.map(item =>
          item.id === id ? { ...item, ...response.data } : item
        )
      );

      setRecentlyBoughtItems(prevItems =>
        prevItems.map(item =>
          item.id === id ? { ...item, ...response.data } : item
        )
      );
    } catch (error) {
      console.error("Failed to add image:", error);
      alert("Failed to add image. Please try again.");
    }
  }, [activeHousehold?.id, activeStore?.id]);


  const handleLongPress = useCallback(async (item) => {
    if (![ROLES.ADMIN, ROLES.EDITOR].includes(role)) return;
    if (!activeHousehold?.id || !activeStore?.id) return;

    try {
      const classificationResponse = await getClassification(activeHousehold.id, activeStore.id, item.id);
      setEditingItem({
        ...item,
        classification: classificationResponse.data
      });
      setShowEditModal(true);
    } catch (error) {
      console.error("Failed to load classification:", error);
      setEditingItem({ ...item, classification: null });
      setShowEditModal(true);
    }
  }, [activeHousehold?.id, activeStore?.id, role]);


  // === Edit Modal Handlers ===
  const handleEditSave = useCallback(async (id, itemName, quantity, classification) => {
    if (!activeHousehold?.id || !activeStore?.id) return;

    try {
      await updateItemWithClassification(activeHousehold.id, activeStore.id, itemName, quantity, classification);

      // Fetch the updated item
      const response = await getItemByName(activeHousehold.id, activeStore.id, itemName);
      const updatedItem = response.data;

      setShowEditModal(false);
      setEditingItem(null);

      setItems(prevItems =>
        prevItems.map(item =>
          item.id === id ? updatedItem : item
        )
      );

      setRecentlyBoughtItems(prevItems =>
        prevItems.map(item =>
          item.id === id ? { ...item, ...updatedItem } : item
        )
      );
    } catch (error) {
      console.error("Failed to update item:", error);
      throw error;
    }
  }, [activeHousehold?.id, activeStore?.id]);


  const handleEditCancel = useCallback(() => {
    setShowEditModal(false);
    setEditingItem(null);
  }, []);


  // === Helper Functions ===
  const groupItemsByZone = (items) => {
    const groups = {};
    items.forEach(item => {
      const zone = item.zone || 'unclassified';
      if (!groups[zone]) {
        groups[zone] = [];
      }
      groups[zone].push(item);
    });
    return groups;
  };


  if (!activeHousehold || !activeStore) {
    return (
      <div className="glist-body">
        <div className="glist-container">
          <h1 className="glist-title">Costco Grocery List</h1>
          <p style={{ textAlign: 'center', marginTop: '2rem', color: 'var(--text-secondary)' }}>
            {!activeHousehold ? 'Loading households...' : 'Loading stores...'}
          </p>
        </div>
      </div>
    );
  }

  if (loading) {
    return (
      <div className="glist-body">
        <div className="glist-container">
          <h1 className="glist-title">Costco Grocery List</h1>
          <StoreTabs />
          <p style={{ textAlign: 'center', marginTop: '2rem' }}>Loading grocery list...</p>
        </div>
      </div>
    );
  }


  return (
    <div className="glist-body">
      <div className="glist-container">
        <h1 className="glist-title">Costco Grocery List</h1>

        <StoreTabs />

        {[ROLES.ADMIN, ROLES.EDITOR].includes(role) && showAddForm && (
          <AddItemForm
            onAdd={handleAdd}
            onSuggest={handleSuggest}
            suggestions={suggestions}
            buttonText={buttonText}
          />
        )}

        <SortDropdown value={sortMode} onChange={setSortMode} />

        {sortMode === "zone" ? (
          (() => {
            const grouped = groupItemsByZone(sortedItems);
            return Object.keys(grouped).map(zone => {
              const isCollapsed = collapsedZones[zone];
              const itemCount = grouped[zone].length;
              return (
                <div key={zone} className="glist-classification-group">
                  <h3
                    className="glist-classification-header clickable"
                    onClick={() => toggleZoneCollapse(zone)}
                  >
                    <span>
                      {zone === 'unclassified' ? 'Unclassified' : zone}
                      <span className="glist-zone-count"> ({itemCount})</span>
                    </span>
                    <span className="glist-zone-indicator">
                      {isCollapsed ? "▼" : "▲"}
                    </span>
                  </h3>
                  {!isCollapsed && (
                    <ul className={`glist-ul ${settings.compactView ? 'compact' : ''}`}>
                      {grouped[zone].map((item) => (
                        <GroceryListItem
                          key={item.id}
                          item={item}
                          allItems={sortedItems}
                          compact={settings.compactView}
                          onClick={(id, quantity) =>
                            [ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(id, quantity)
                          }
                          onImageAdded={
                            [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
                          }
                          onLongPress={
                            [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleLongPress : null
                          }
                        />
                      ))}
                    </ul>
                  )}
                </div>
              );
            });
          })()
        ) : (
          <ul className={`glist-ul ${settings.compactView ? 'compact' : ''}`}>
            {sortedItems.map((item) => (
              <GroceryListItem
                key={item.id}
                item={item}
                allItems={sortedItems}
                compact={settings.compactView}
                onClick={(id, quantity) =>
                  [ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(id, quantity)
                }
                onImageAdded={
                  [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
                }
                onLongPress={
                  [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleLongPress : null
                }
              />
            ))}
          </ul>
        )}

        {recentlyBoughtItems.length > 0 && settings.showRecentlyBought && (
          <>
            <h2
              className="glist-section-title clickable"
              onClick={() => setRecentlyBoughtCollapsed(!recentlyBoughtCollapsed)}
            >
              <span>Recently Bought (24HR)</span>
              <span className="glist-section-indicator">
                {recentlyBoughtCollapsed ? "▼" : "▲"}
              </span>
            </h2>

            {!recentlyBoughtCollapsed && (
              <>
                <ul className={`glist-ul ${settings.compactView ? 'compact' : ''}`}>
                  {recentlyBoughtItems.slice(0, recentlyBoughtDisplayCount).map((item) => (
                    <GroceryListItem
                      key={item.id}
                      item={item}
                      allItems={recentlyBoughtItems}
                      compact={settings.compactView}
                      onClick={null}
                      onImageAdded={
                        [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
                      }
                      onLongPress={
                        [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleLongPress : null
                      }
                    />
                  ))}
                </ul>
                {recentlyBoughtDisplayCount < recentlyBoughtItems.length && (
                  <div style={{ textAlign: 'center', marginTop: '1rem' }}>
                    <button
                      className="glist-show-more-btn"
                      onClick={() => setRecentlyBoughtDisplayCount(prev => prev + 10)}
                    >
                      Show More ({recentlyBoughtItems.length - recentlyBoughtDisplayCount} remaining)
                    </button>
                  </div>
                )}
              </>
            )}
          </>
        )}
      </div>

      {[ROLES.ADMIN, ROLES.EDITOR].includes(role) && (
        <FloatingActionButton
          isOpen={showAddForm}
          onClick={() => setShowAddForm(!showAddForm)}
        />
      )}

      {showAddDetailsModal && pendingItem && (
        <AddItemWithDetailsModal
          itemName={pendingItem.itemName}
          onConfirm={handleAddWithDetails}
          onSkip={handleAddDetailsSkip}
          onCancel={handleAddDetailsCancel}
        />
      )}

      {showSimilarModal && similarItemSuggestion && (
        <SimilarItemModal
          originalName={similarItemSuggestion.originalName}
          suggestedName={similarItemSuggestion.suggestedItem.item_name}
          onCancel={handleSimilarCancel}
          onNo={handleSimilarNo}
          onYes={handleSimilarYes}
        />
      )}

      {showEditModal && editingItem && (
        <EditItemModal
          item={editingItem}
          onSave={handleEditSave}
          onCancel={handleEditCancel}
          onImageUpdate={handleImageAdded}
        />
      )}

      {showConfirmAddExisting && confirmAddExistingData && (
        <ConfirmAddExistingModal
          itemName={confirmAddExistingData.itemName}
          currentQuantity={confirmAddExistingData.currentQuantity}
          addingQuantity={confirmAddExistingData.addingQuantity}
          onConfirm={handleConfirmAddExisting}
          onCancel={() => {
            setShowConfirmAddExisting(false);
            setConfirmAddExistingData(null);
          }}
        />
      )}
    </div>
  );
}