import { getDb } from './db.js';

/**
 * Record a stock movement and update parts.quantity_on_hand atomically.
 * Returns the new on-hand quantity.
 *
 *   type:     'in' | 'out' | 'adjust'
 *   quantity: positive integer
 *     - 'in':     adds to on-hand
 *     - 'out':    subtracts from on-hand (stored as negative)
 *     - 'adjust': sets on-hand to exactly this number (delta stored)
 */
export function recordMovement(input) {
  const db = getDb();
  const partId = Number(input.part_id);
  const type   = input.movement_type;
  const qty    = Math.abs(Number(input.quantity || 0));
  const unitPrice = toDirams(input.unit_price);
  const supplierId = input.supplier_id ? Number(input.supplier_id) : null;
  const reference = input.reference?.trim() || null;
  const notes = input.notes?.trim() || null;

  if (!partId)               throw new Error('part_id required');
  if (!['in','out','adjust'].includes(type)) throw new Error('invalid movement_type');
  if (!Number.isInteger(qty) || qty < 0)     throw new Error('quantity must be a non-negative integer');

  const tx = db.transaction(() => {
    const part = db.prepare(`SELECT id, quantity_on_hand FROM parts WHERE id = ?`).get(partId);
    if (!part) throw new Error(`part ${partId} not found`);

    let storedQty;     // what we save in stock_movements.quantity
    let newOnHand;
    if (type === 'in') {
      storedQty = qty;
      newOnHand = part.quantity_on_hand + qty;
    } else if (type === 'out') {
      if (qty > part.quantity_on_hand) {
        throw new Error(`not enough stock (have ${part.quantity_on_hand}, need ${qty})`);
      }
      storedQty = -qty;
      newOnHand = part.quantity_on_hand - qty;
    } else { // adjust → qty is the new total
      storedQty = qty - part.quantity_on_hand;
      newOnHand = qty;
    }

    db.prepare(`
      INSERT INTO stock_movements
        (part_id, movement_type, quantity, unit_price, supplier_id, reference, notes)
      VALUES (?, ?, ?, ?, ?, ?, ?)
    `).run(partId, type, storedQty, unitPrice, supplierId, reference, notes);

    db.prepare(`
      UPDATE parts SET quantity_on_hand = ?, updated_at = datetime('now') WHERE id = ?
    `).run(newOnHand, partId);

    return newOnHand;
  });

  return tx();
}

export function recentMovementsForPart(partId, limit = 20) {
  return getDb().prepare(`
    SELECT m.*, s.name AS supplier_name
    FROM stock_movements m
    LEFT JOIN suppliers s ON s.id = m.supplier_id
    WHERE m.part_id = ?
    ORDER BY m.created_at DESC, m.id DESC
    LIMIT ?
  `).all(partId, limit);
}

export function recentMovements(limit = 25) {
  return getDb().prepare(`
    SELECT m.*, p.sku, p.name_en, p.name_tg, s.name AS supplier_name
    FROM stock_movements m
    JOIN parts p     ON p.id = m.part_id
    LEFT JOIN suppliers s ON s.id = m.supplier_id
    ORDER BY m.created_at DESC, m.id DESC
    LIMIT ?
  `).all(limit);
}

function toDirams(value) {
  if (value === '' || value == null) return null;
  const num = typeof value === 'number' ? value : Number(String(value).replace(',', '.'));
  if (!Number.isFinite(num)) return null;
  return Math.round(num * 100);
}
