const pool = require("../db/pool");


exports.getUnboughtItems = async () => {
  const result = await pool.query(
    `SELECT 
      gl.id, 
      LOWER(gl.item_name) AS item_name,
      gl.quantity, 
      gl.bought,
      ENCODE(gl.item_image, 'base64') as item_image,
      gl.image_mime_type,
      (
        SELECT ARRAY_AGG(DISTINCT u.name)
        FROM (
          SELECT DISTINCT gh.added_by
          FROM grocery_history gh
          WHERE gh.list_item_id = gl.id
          ORDER BY gh.added_by
        ) gh
        JOIN users u ON gh.added_by = u.id
      ) as added_by_users,
      gl.modified_on as last_added_on,
      ic.item_type,
      ic.item_group,
      ic.zone
    FROM grocery_list gl
    LEFT JOIN item_classification ic ON gl.id = ic.id
    WHERE gl.bought = FALSE
    ORDER BY gl.id ASC`
  );
  return result.rows;
};

exports.getItemByName = async (itemName) => {
  const result = await pool.query(
    `SELECT 
      gl.id, 
      LOWER(gl.item_name) AS item_name,
      gl.quantity, 
      gl.bought,
      ENCODE(gl.item_image, 'base64') as item_image,
      gl.image_mime_type,
      (
        SELECT ARRAY_AGG(DISTINCT u.name)
        FROM (
          SELECT DISTINCT gh.added_by
          FROM grocery_history gh
          WHERE gh.list_item_id = gl.id
          ORDER BY gh.added_by
        ) gh
        JOIN users u ON gh.added_by = u.id
      ) as added_by_users,
      gl.modified_on as last_added_on,
      ic.item_type,
      ic.item_group,
      ic.zone
    FROM grocery_list gl
    LEFT JOIN item_classification ic ON gl.id = ic.id
    WHERE gl.item_name ILIKE $1`,
    [itemName]
  );

  return result.rows[0] || null;
};


exports.addOrUpdateItem = async (itemName, quantity, userId, imageBuffer = null, mimeType = null) => {
  const lowerItemName = itemName.toLowerCase();

  const result = await pool.query(
    "SELECT id, bought FROM grocery_list WHERE item_name ILIKE $1",
    [lowerItemName]
  );

  if (result.rowCount > 0) {
    // Update existing item
    if (imageBuffer && mimeType) {
      await pool.query(
        `UPDATE grocery_list 
        SET quantity = $1, 
          bought = FALSE,
          item_image = $3,
          image_mime_type = $4,
          modified_on = NOW()
        WHERE id = $2`,
        [quantity, result.rows[0].id, imageBuffer, mimeType]
      );
    } else {
      await pool.query(
        `UPDATE grocery_list 
        SET quantity = $1, 
          bought = FALSE,
          modified_on = NOW()
        WHERE id = $2`,
        [quantity, result.rows[0].id]
      );
    }
    return result.rows[0].id;
  } else {
    // Insert new item
    const insert = await pool.query(
      `INSERT INTO grocery_list 
      (item_name, quantity, added_by, item_image, image_mime_type) 
      VALUES ($1, $2, $3, $4, $5) RETURNING id`,
      [lowerItemName, quantity, userId, imageBuffer, mimeType]
    );
    return insert.rows[0].id;
  }
};


exports.setBought = async (id, userId, quantityBought) => {
  // Get current item
  const item = await pool.query(
    "SELECT quantity FROM grocery_list WHERE id = $1",
    [id]
  );

  if (!item.rows[0]) return;

  const currentQuantity = item.rows[0].quantity;
  const remainingQuantity = currentQuantity - quantityBought;

  if (remainingQuantity <= 0) {
    // Mark as bought if all quantity is purchased
    await pool.query(
      "UPDATE grocery_list SET bought = TRUE, modified_on = NOW() WHERE id = $1",
      [id]
    );
  } else {
    // Reduce quantity if partial purchase
    await pool.query(
      "UPDATE grocery_list SET quantity = $1, modified_on = NOW() WHERE id = $2",
      [remainingQuantity, id]
    );
  }
};


exports.addHistoryRecord = async (itemId, quantity, userId) => {
  await pool.query(
    `INSERT INTO grocery_history (list_item_id, quantity, added_by, added_on)
     VALUES ($1, $2, $3, NOW())`,
    [itemId, quantity, userId]
  );
};


exports.getSuggestions = async (query) => {
  const result = await pool.query(
    `SELECT DISTINCT LOWER(item_name) as item_name 
       FROM grocery_list 
       WHERE item_name ILIKE $1
       LIMIT 10`,
    [`%${query}%`]
  );
  return result.rows;
};

exports.getRecentlyBoughtItems = async () => {
  const result = await pool.query(
    `SELECT 
      gl.id, 
      LOWER(gl.item_name) AS item_name,
      gl.quantity, 
      gl.bought,
      ENCODE(gl.item_image, 'base64') as item_image,
      gl.image_mime_type,
      (
        SELECT ARRAY_AGG(DISTINCT u.name)
        FROM (
          SELECT DISTINCT gh.added_by
          FROM grocery_history gh
          WHERE gh.list_item_id = gl.id
          ORDER BY gh.added_by
        ) gh
        JOIN users u ON gh.added_by = u.id
      ) as added_by_users,
      gl.modified_on as last_added_on
    FROM grocery_list gl
    WHERE gl.bought = TRUE 
      AND gl.modified_on >= NOW() - INTERVAL '24 hours'
    ORDER BY gl.modified_on DESC`
  );
  return result.rows;
};

// Classification methods
exports.getClassification = async (itemId) => {
  const result = await pool.query(
    `SELECT item_type, item_group, zone, confidence, source
     FROM item_classification
     WHERE id = $1`,
    [itemId]
  );
  return result.rows[0] || null;
};

exports.upsertClassification = async (itemId, classification) => {
  const { item_type, item_group, zone, confidence, source } = classification;

  const result = await pool.query(
    `INSERT INTO item_classification (id, item_type, item_group, zone, confidence, source)
     VALUES ($1, $2, $3, $4, $5, $6)
     ON CONFLICT (id) 
     DO UPDATE SET 
       item_type = EXCLUDED.item_type,
       item_group = EXCLUDED.item_group,
       zone = EXCLUDED.zone,
       confidence = EXCLUDED.confidence,
       source = EXCLUDED.source
     RETURNING *`,
    [itemId, item_type, item_group, zone, confidence, source]
  );
  return result.rows[0];
};

exports.updateItem = async (id, itemName, quantity) => {
  const result = await pool.query(
    `UPDATE grocery_list 
     SET item_name = $2, quantity = $3, modified_on = NOW()
     WHERE id = $1
     RETURNING *`,
    [id, itemName, quantity]
  );
  return result.rows[0];
};

