const List = require("../models/list.model.v2");
const householdModel = require("../models/household.model");
const { isValidItemType, isValidItemGroup, isValidZone } = require("../constants/classifications");
const { sendError } = require("../utils/http");
const { logError } = require("../utils/logger");

/**
 * Get list items for household and store
 * GET /households/:householdId/stores/:storeId/list
 */
exports.getList = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const items = await List.getHouseholdStoreList(householdId, storeId);
    res.json({ items });
  } catch (error) {
    logError(req, "listsV2.getList", error);
    sendError(res, 500, "Failed to get list");
  }
};

/**
 * Get specific item by name
 * GET /households/:householdId/stores/:storeId/list/item
 */
exports.getItemByName = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name } = req.query;

    if (!item_name) {
      return sendError(res, 400, "Item name is required");
    }

    const item = await List.getItemByName(householdId, storeId, item_name);
    if (!item) {
      return sendError(res, 404, "Item not found");
    }

    res.json(item);
  } catch (error) {
    logError(req, "listsV2.getItemByName", error);
    sendError(res, 500, "Failed to get item");
  }
};

/**
 * Add or update item in household store list
 * POST /households/:householdId/stores/:storeId/list/add
 */
exports.addItem = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name, quantity, notes, added_for_user_id } = req.body;
    const userId = req.user.id;
    let historyUserId = userId;

    if (!item_name || item_name.trim() === "") {
      return sendError(res, 400, "Item name is required");
    }

    if (added_for_user_id !== undefined && added_for_user_id !== null && String(added_for_user_id).trim() !== "") {
      const rawAddedForUserId = String(added_for_user_id).trim();
      if (!/^\d+$/.test(rawAddedForUserId)) {
        return sendError(res, 400, "Added-for user ID must be a positive integer");
      }

      const parsedUserId = Number.parseInt(rawAddedForUserId, 10);

      if (!Number.isInteger(parsedUserId) || parsedUserId <= 0) {
        return sendError(res, 400, "Added-for user ID must be a positive integer");
      }

      const isMember = await householdModel.isHouseholdMember(householdId, parsedUserId);
      if (!isMember) {
        return sendError(res, 400, "Selected user is not a member of this household");
      }

      historyUserId = parsedUserId;
    }

    // Get processed image if uploaded
    const imageBuffer = req.processedImage?.buffer || null;
    const mimeType = req.processedImage?.mimeType || null;

    const result = await List.addOrUpdateItem(
      householdId,
      storeId,
      item_name,
      quantity || "1",
      userId,
      imageBuffer,
      mimeType,
      notes
    );

    // Add history record
    await List.addHistoryRecord(result.listId, quantity || "1", historyUserId);

    res.json({
      message: result.isNew ? "Item added" : "Item updated",
      item: {
        id: result.listId,
        item_name: result.itemName,
        quantity: quantity || "1",
        bought: false
      }
    });
  } catch (error) {
    logError(req, "listsV2.addItem", error);
    sendError(res, 500, "Failed to add item");
  }
};

/**
 * Mark item as bought or unbought
 * PATCH /households/:householdId/stores/:storeId/list/item
 */
exports.markBought = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name, bought, quantity_bought } = req.body;

    if (!item_name) return sendError(res, 400, "Item name is required");

    const item = await List.getItemByName(householdId, storeId, item_name);
    if (!item) return sendError(res, 404, "Item not found");


    // Update bought status (with optional partial purchase)
    await List.setBought(item.id, bought, quantity_bought);

    res.json({ message: bought ? "Item marked as bought" : "Item unmarked" });
  } catch (error) {
    logError(req, "listsV2.markBought", error);
    sendError(res, 500, "Failed to update item");
  }
};

/**
 * Update item details (quantity, notes)
 * PUT /households/:householdId/stores/:storeId/list/item
 */
exports.updateItem = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name, quantity, notes } = req.body;

    if (!item_name) {
      return sendError(res, 400, "Item name is required");
    }

    // Get the list item
    const item = await List.getItemByName(householdId, storeId, item_name);
    if (!item) {
      return sendError(res, 404, "Item not found");
    }

    // Update item
    await List.updateItem(item.id, item_name, quantity, notes);

    res.json({
      message: "Item updated",
      item: {
        id: item.id,
        item_name,
        quantity,
        notes
      }
    });
  } catch (error) {
    logError(req, "listsV2.updateItem", error);
    sendError(res, 500, "Failed to update item");
  }
};

/**
 * Delete item from list
 * DELETE /households/:householdId/stores/:storeId/list/item
 */
exports.deleteItem = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name } = req.body;

    if (!item_name) {
      return sendError(res, 400, "Item name is required");
    }

    // Get the list item
    const item = await List.getItemByName(householdId, storeId, item_name);
    if (!item) {
      return sendError(res, 404, "Item not found");
    }

    await List.deleteItem(item.id);

    res.json({ message: "Item deleted" });
  } catch (error) {
    logError(req, "listsV2.deleteItem", error);
    sendError(res, 500, "Failed to delete item");
  }
};

/**
 * Get item suggestions based on query
 * GET /households/:householdId/stores/:storeId/list/suggestions
 */
exports.getSuggestions = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { query } = req.query;

    const suggestions = await List.getSuggestions(query || "", householdId, storeId);
    res.json(suggestions);
  } catch (error) {
    logError(req, "listsV2.getSuggestions", error);
    sendError(res, 500, "Failed to get suggestions");
  }
};

/**
 * Get recently bought items
 * GET /households/:householdId/stores/:storeId/list/recent
 */
exports.getRecentlyBought = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const items = await List.getRecentlyBoughtItems(householdId, storeId);
    res.json(items);
  } catch (error) {
    logError(req, "listsV2.getRecentlyBought", error);
    sendError(res, 500, "Failed to get recent items");
  }
};

/**
 * Get item classification
 * GET /households/:householdId/stores/:storeId/list/classification
 */
exports.getClassification = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name } = req.query;

    if (!item_name) {
      return sendError(res, 400, "Item name is required");
    }

    // Get item ID from name
    const item = await List.getItemByName(householdId, storeId, item_name);
    if (!item) {
      return res.json({ classification: null });
    }

    const classification = await List.getClassification(householdId, item.item_id);
    res.json({ classification });
  } catch (error) {
    logError(req, "listsV2.getClassification", error);
    sendError(res, 500, "Failed to get classification");
  }
};

/**
 * Set/update item classification
 * POST /households/:householdId/stores/:storeId/list/classification
 */
exports.setClassification = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name, classification } = req.body;

    if (!item_name) {
      return sendError(res, 400, "Item name is required");
    }

    if (!classification) {
      return sendError(res, 400, "Classification is required");
    }

    // Validate classification
    const validClassifications = ['produce', 'dairy', 'meat', 'bakery', 'frozen', 'pantry', 'snacks', 'beverages', 'household', 'other'];
    if (!validClassifications.includes(classification)) {
      return sendError(res, 400, "Invalid classification value");
    }

    // Get item - add to master items if not exists
    const item = await List.getItemByName(householdId, storeId, item_name);
    let itemId;

    if (!item) {
      // Item doesn't exist in list, need to get from items table or create
      const itemResult = await List.addOrUpdateItem(
        householdId,
        storeId,
        item_name,
        "1",
        req.user.id,
        null,
        null
      );
      itemId = itemResult.itemId;
    } else {
      itemId = item.item_id;
    }

    // Set classification (using item_type field for simplicity)
    await List.upsertClassification(householdId, itemId, {
      item_type: classification,
      item_group: null,
      zone: null
    });

    res.json({ message: "Classification set", classification });
  } catch (error) {
    logError(req, "listsV2.setClassification", error);
    sendError(res, 500, "Failed to set classification");
  }
};

/**
 * Update item image
 * POST /households/:householdId/stores/:storeId/list/update-image
 */
exports.updateItemImage = async (req, res) => {
  try {
    const { householdId, storeId } = req.params;
    const { item_name, quantity } = req.body;
    const userId = req.user.id;

    // Get processed image
    const imageBuffer = req.processedImage?.buffer || null;
    const mimeType = req.processedImage?.mimeType || null;

    if (!imageBuffer) {
      return sendError(res, 400, "No image provided");
    }

    // Update the item with new image
    await List.addOrUpdateItem(householdId, storeId, item_name, quantity, userId, imageBuffer, mimeType);

    res.json({ message: "Image updated successfully" });
  } catch (error) {
    logError(req, "listsV2.updateItemImage", error);
    sendError(res, 500, "Failed to update image");
  }
};
