const pool = require('../config/db');

async function getAll(req, res) {
  try {
    const { search, category_id, low_stock } = req.query;
    let query = `
      SELECT p.*, c.name AS category_name,
        (p.quantity * p.unit_price) AS total_value
      FROM products p
      LEFT JOIN categories c ON p.category_id = c.id
      WHERE 1=1
    `;
    const params = [];

    if (search) {
      query += ' AND (p.name LIKE ? OR p.sku LIKE ? OR p.supplier LIKE ?)';
      const term = `%${search}%`;
      params.push(term, term, term);
    }

    if (category_id) {
      query += ' AND p.category_id = ?';
      params.push(category_id);
    }

    if (low_stock === 'true') {
      query += ' AND p.quantity <= p.min_stock_level';
    }

    query += ' ORDER BY p.name';

    const [products] = await pool.query(query, params);
    res.json({ products });
  } catch (error) {
    console.error('Get products error:', error);
    res.status(500).json({ message: 'Server error' });
  }
}

async function getById(req, res) {
  try {
    const [products] = await pool.query(
      `SELECT p.*, c.name AS category_name FROM products p
       LEFT JOIN categories c ON p.category_id = c.id WHERE p.id = ?`,
      [req.params.id]
    );

    if (products.length === 0) {
      return res.status(404).json({ message: 'Product not found' });
    }

    res.json({ product: products[0] });
  } catch (error) {
    console.error('Get product error:', error);
    res.status(500).json({ message: 'Server error' });
  }
}

async function create(req, res) {
  try {
    const { name, sku, description, category_id, quantity, min_stock_level, unit_price, supplier, location } = req.body;

    if (!name || !sku) {
      return res.status(400).json({ message: 'Name and SKU are required' });
    }

    const [result] = await pool.query(
      `INSERT INTO products (name, sku, description, category_id, quantity, min_stock_level, unit_price, supplier, location, created_by)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
      [
        name,
        sku,
        description || null,
        category_id || null,
        quantity || 0,
        min_stock_level ?? 10,
        unit_price || 0,
        supplier || null,
        location || null,
        req.user.id,
      ]
    );

    if (quantity && quantity > 0) {
      await pool.query(
        `INSERT INTO stock_movements (product_id, type, quantity, previous_quantity, new_quantity, reason, user_id)
         VALUES (?, 'in', ?, 0, ?, 'Initial stock', ?)`,
        [result.insertId, quantity, quantity, req.user.id]
      );
    }

    res.status(201).json({
      message: 'Product created',
      product: { id: result.insertId, name, sku },
    });
  } catch (error) {
    if (error.code === 'ER_DUP_ENTRY') {
      return res.status(409).json({ message: 'SKU already exists' });
    }
    console.error('Create product error:', error);
    res.status(500).json({ message: 'Server error' });
  }
}

async function update(req, res) {
  try {
    const { name, sku, description, category_id, min_stock_level, unit_price, supplier, location } = req.body;
    const { id } = req.params;

    const [result] = await pool.query(
      `UPDATE products SET name = ?, sku = ?, description = ?, category_id = ?,
       min_stock_level = ?, unit_price = ?, supplier = ?, location = ? WHERE id = ?`,
      [name, sku, description || null, category_id || null, min_stock_level ?? 10, unit_price || 0, supplier || null, location || null, id]
    );

    if (result.affectedRows === 0) {
      return res.status(404).json({ message: 'Product not found' });
    }

    res.json({ message: 'Product updated' });
  } catch (error) {
    if (error.code === 'ER_DUP_ENTRY') {
      return res.status(409).json({ message: 'SKU already exists' });
    }
    console.error('Update product error:', error);
    res.status(500).json({ message: 'Server error' });
  }
}

async function remove(req, res) {
  try {
    const [result] = await pool.query('DELETE FROM products WHERE id = ?', [req.params.id]);

    if (result.affectedRows === 0) {
      return res.status(404).json({ message: 'Product not found' });
    }

    res.json({ message: 'Product deleted' });
  } catch (error) {
    console.error('Delete product error:', error);
    res.status(500).json({ message: 'Server error' });
  }
}

async function adjustStock(req, res) {
  const connection = await pool.getConnection();
  try {
    const { type, quantity, reason, reference_no } = req.body;
    const productId = req.params.id;

    if (!type || !['in', 'out', 'adjustment'].includes(type)) {
      return res.status(400).json({ message: 'Valid type (in, out, adjustment) is required' });
    }

    if (!quantity || quantity <= 0) {
      return res.status(400).json({ message: 'Quantity must be greater than 0' });
    }

    await connection.beginTransaction();

    const [products] = await connection.query('SELECT quantity FROM products WHERE id = ? FOR UPDATE', [productId]);

    if (products.length === 0) {
      await connection.rollback();
      return res.status(404).json({ message: 'Product not found' });
    }

    const previousQty = products[0].quantity;
    let newQty;

    if (type === 'in') {
      newQty = previousQty + quantity;
    } else if (type === 'out') {
      if (previousQty < quantity) {
        await connection.rollback();
        return res.status(400).json({ message: 'Insufficient stock' });
      }
      newQty = previousQty - quantity;
    } else {
      newQty = quantity;
    }

    await connection.query('UPDATE products SET quantity = ? WHERE id = ?', [newQty, productId]);

    await connection.query(
      `INSERT INTO stock_movements (product_id, type, quantity, previous_quantity, new_quantity, reason, reference_no, user_id)
       VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
      [productId, type, quantity, previousQty, newQty, reason || null, reference_no || null, req.user.id]
    );

    await connection.commit();

    res.json({
      message: 'Stock updated',
      previous_quantity: previousQty,
      new_quantity: newQty,
    });
  } catch (error) {
    await connection.rollback();
    console.error('Adjust stock error:', error);
    res.status(500).json({ message: 'Server error' });
  } finally {
    connection.release();
  }
}

module.exports = { getAll, getById, create, update, remove, adjustStock };
