import { useContext, useEffect, 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 EditItemModal from "../components/modals/EditItemModal";
import SimilarItemModal from "../components/modals/SimilarItemModal";
import { ROLES } from "../constants/roles";
import { AuthContext } from "../context/AuthContext";
import "../styles/pages/GroceryList.css";
import { findSimilarItems } from "../utils/stringSimilarity";

export default function GroceryList() {
  const { role } = useContext(AuthContext);

  const [items, setItems] = useState([]);
  const [recentlyBoughtItems, setRecentlyBoughtItems] = useState([]);
  const [recentlyBoughtDisplayCount, setRecentlyBoughtDisplayCount] = useState(10);
  const [sortedItems, setSortedItems] = useState([]);
  const [sortMode, setSortMode] = useState("zone");
  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 loadItems = async () => {
    setLoading(true);
    const res = await getList();
    console.log(res.data);
    setItems(res.data);
    setLoading(false);
  };

  const loadRecentlyBought = async () => {
    try {
      const res = await getRecentlyBought();
      setRecentlyBoughtItems(res.data);
    } catch (error) {
      console.error("Failed to load recently bought items:", error);
      setRecentlyBoughtItems([]);
    }
  };

  useEffect(() => {
    loadItems();
    loadRecentlyBought();
  }, []);

  useEffect(() => {
    let 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.item_type && b.item_type) return 1;
        if (a.item_type && !b.item_type) return -1;
        if (!a.item_type && !b.item_type) return a.item_name.localeCompare(b.item_name);

        // Sort 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;

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

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

    setSortedItems(sorted);
  }, [items, sortMode]);

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

    // Combine both unbought and recently bought items for similarity checking
    const allItems = [...items, ...recentlyBoughtItems];

    // Check if exact match exists (case-insensitive)
    const lowerText = text.toLowerCase().trim();
    const exactMatch = allItems.find(item => item.item_name.toLowerCase() === lowerText);

    if (exactMatch) {
      setButtonText("Add");
    } else {
      setButtonText("Create + Add");
    }

    try {
      let suggestions = await getSuggestions(text);
      suggestions = suggestions.data.map(s => s.item_name);
      setSuggestions(suggestions);
    } catch {
      setSuggestions([]);
    }
  };

  const handleAdd = async (itemName, quantity) => {
    if (!itemName.trim()) return;

    const lowerItemName = itemName.toLowerCase().trim();

    // First check if exact item exists in database (case-insensitive)
    let existingItem = null;
    try {
      const response = await getItemByName(itemName);
      existingItem = response.data;
    } catch {
      existingItem = null;
    }

    // If exact item exists, skip similarity check and process directly
    if (existingItem) {
      await processItemAddition(itemName, quantity);
      return;
    }

    // Only check for similar items if exact item doesn't exist
    const allItems = [...items, ...recentlyBoughtItems];
    const similar = findSimilarItems(itemName, allItems, 80);
    if (similar.length > 0) {
      // Show modal and wait for user decision
      setSimilarItemSuggestion({ originalName: itemName, suggestedItem: similar[0], quantity });
      setShowSimilarModal(true);
      return;
    }

    // Continue with normal flow for new items
    await processItemAddition(itemName, quantity);
  };

  const processItemAddition = async (itemName, quantity) => {

    // Check if item exists in database (case-insensitive)
    let existingItem = null;
    try {
      const response = await getItemByName(itemName);
      existingItem = response.data;
    } catch {
      existingItem = null;
    }

    if (existingItem && existingItem.bought === false) {
      // Item exists and is unbought - update quantity
      const currentQuantity = existingItem.quantity;
      const newQuantity = currentQuantity + quantity;
      const yes = window.confirm(
        `Item "${itemName}" already exists in the list. Do you want to update its quantity from ${currentQuantity} to ${newQuantity}?`
      );
      if (!yes) return;

      await addItem(itemName, newQuantity, null);
      setSuggestions([]);
      setButtonText("Add Item");
      loadItems();
    } else if (existingItem) {
      // Item exists in database (was previously bought) - just add quantity
      await addItem(itemName, quantity, null);
      setSuggestions([]);
      setButtonText("Add Item");
      loadItems();
    } else {
      // NEW ITEM - show combined add details modal
      setPendingItem({ itemName, quantity });
      setShowAddDetailsModal(true);
    }
  };

  const handleSimilarCancel = () => {
    setShowSimilarModal(false);
    setSimilarItemSuggestion(null);
  };

  const handleSimilarNo = async () => {
    if (!similarItemSuggestion) return;
    setShowSimilarModal(false);
    // Create new item with original name
    await processItemAddition(similarItemSuggestion.originalName, similarItemSuggestion.quantity);
    setSimilarItemSuggestion(null);
  };

  const handleSimilarYes = async () => {
    if (!similarItemSuggestion) return;
    setShowSimilarModal(false);
    // Use suggested item name
    await processItemAddition(similarItemSuggestion.suggestedItem.item_name, similarItemSuggestion.quantity);
    setSimilarItemSuggestion(null);
  };

  const handleAddDetailsConfirm = async (imageFile, classification) => {
    if (!pendingItem) return;

    try {
      // Add item to grocery_list with image
      await addItem(pendingItem.itemName, pendingItem.quantity, imageFile);

      // If classification provided, add it
      if (classification) {
        const itemResponse = await getItemByName(pendingItem.itemName);
        const itemId = itemResponse.data.id;
        await updateItemWithClassification(itemId, undefined, undefined, classification);
      }

      setShowAddDetailsModal(false);
      setPendingItem(null);
      setSuggestions([]);
      setButtonText("Add Item");
      loadItems();
    } catch (error) {
      console.error("Failed to add item:", error);
      alert("Failed to add item. Please try again.");
    }
  };

  const handleAddDetailsSkip = async () => {
    if (!pendingItem) return;

    try {
      // Add item without image or classification
      await addItem(pendingItem.itemName, pendingItem.quantity, null);

      setShowAddDetailsModal(false);
      setPendingItem(null);
      setSuggestions([]);
      setButtonText("Add Item");
      loadItems();
    } catch (error) {
      console.error("Failed to add item:", error);
      alert("Failed to add item. Please try again.");
    }
  };

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



  const handleBought = async (id, quantity) => {
    await markBought(id);
    loadItems();
    loadRecentlyBought();
  };

  const handleImageAdded = async (id, itemName, quantity, imageFile) => {
    try {
      await updateItemImage(id, itemName, quantity, imageFile);
      loadItems(); // Reload to show new image
    } catch (error) {
      console.error("Failed to add image:", error);
      alert("Failed to add image. Please try again.");
    }
  };

  const handleLongPress = async (item) => {
    if (![ROLES.ADMIN, ROLES.EDITOR].includes(role)) return;

    try {
      // Fetch existing classification
      const classificationResponse = await getClassification(item.id);
      setEditingItem({
        ...item,
        classification: classificationResponse.data
      });
      setShowEditModal(true);
    } catch (error) {
      console.error("Failed to load classification:", error);
      setEditingItem({ ...item, classification: null });
      setShowEditModal(true);
    }
  };

  const handleEditSave = async (id, itemName, quantity, classification) => {
    try {
      await updateItemWithClassification(id, itemName, quantity, classification);
      setShowEditModal(false);
      setEditingItem(null);
      loadItems();
      loadRecentlyBought();
    } catch (error) {
      console.error("Failed to update item:", error);
      throw error; // Re-throw to let modal handle it
    }
  };

  const handleEditCancel = () => {
    setShowEditModal(false);
    setEditingItem(null);
  };

  // Group items by zone for classification view
  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 (loading) return <p>Loading...</p>;

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


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

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

        {sortMode === "zone" ? (
          // Grouped view by zone
          (() => {
            const grouped = groupItemsByZone(sortedItems);
            return Object.keys(grouped).map(zone => (
              <div key={zone} className="glist-classification-group">
                <h3 className="glist-classification-header">
                  {zone === 'unclassified' ? 'Unclassified' : zone}
                </h3>
                <ul className="glist-ul">
                  {grouped[zone].map((item) => (
                    <GroceryListItem
                      key={item.id}
                      item={item}
                      onClick={(quantity) =>
                        [ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(item.id, quantity)
                      }
                      onImageAdded={
                        [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
                      }
                      onLongPress={
                        [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleLongPress : null
                      }
                    />
                  ))}
                </ul>
              </div>
            ));
          })()
        ) : (
          // Regular flat list view
          <ul className="glist-ul">
            {sortedItems.map((item) => (
              <GroceryListItem
                key={item.id}
                item={item}
                onClick={(quantity) =>
                  [ROLES.ADMIN, ROLES.EDITOR].includes(role) && handleBought(item.id, quantity)
                }
                onImageAdded={
                  [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleImageAdded : null
                }
                onLongPress={
                  [ROLES.ADMIN, ROLES.EDITOR].includes(role) ? handleLongPress : null
                }
              />
            ))}
          </ul>
        )}

        {recentlyBoughtItems.length > 0 && (
          <>
            <h2 className="glist-section-title">Recently Bought (24HR)</h2>
            <ul className="glist-ul">
              {recentlyBoughtItems.slice(0, recentlyBoughtDisplayCount).map((item) => (
                <GroceryListItem
                  key={item.id}
                  item={item}
                  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={handleAddDetailsConfirm}
          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}
        />
      )}
    </div>
  );
}
