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

// Columns the user can sort the parts list by. Anything else is ignored.
const SORTABLE = new Set([
  'sku', 'name_en', 'name_tg', 'quantity_on_hand',
  'sale_price', 'cost_price', 'reorder_level', 'updated_at'
]);

export function listParts({ q = '', sort = 'sku', dir = 'asc', categoryIds = [] } = {}) {
  const db = getDb();
  const col = SORTABLE.has(sort) ? sort : 'sku';
  const order = dir === 'desc' ? 'DESC' : 'ASC';

  const where = [];
  const params = {};
  if (q && q.trim()) {
    where.push(`(p.sku LIKE @q OR p.name_en LIKE @q OR p.name_tg LIKE @q OR p.barcode LIKE @q)`);
    params.q = `%${q.trim()}%`;
  }
  if (categoryIds && categoryIds.length) {
    const placeholders = categoryIds.map((_, i) => `@cat${i}`).join(',');
    where.push(`p.category_id IN (${placeholders})`);
    categoryIds.forEach((id, i) => { params[`cat${i}`] = id; });
  }
  const whereSql = where.length ? `WHERE ${where.join(' AND ')}` : '';

  const sql = `
    SELECT p.*, c.name_en AS category_name_en, c.name_tg AS category_name_tg
    FROM parts p
    LEFT JOIN categories c ON c.id = p.category_id
    ${whereSql}
    ORDER BY ${col} ${order}
  `;
  return db.prepare(sql).all(params);
}

export function getPart(id) {
  return getDb().prepare(`
    SELECT p.*, c.name_en AS category_name_en, c.name_tg AS category_name_tg
    FROM parts p
    LEFT JOIN categories c ON c.id = p.category_id
    WHERE p.id = ?
  `).get(id);
}

export function getPartBySku(sku) {
  return getDb().prepare(`SELECT * FROM parts WHERE sku = ?`).get(sku);
}

export function listCategories() {
  return getDb()
    .prepare(`SELECT * FROM categories ORDER BY sort_order, name_en`)
    .all();
}

// Categories that have at least one part — used to build the filter chips on
// the parts list so we don't offer empty options.
export function categoriesWithParts() {
  return getDb().prepare(`
    SELECT c.* FROM categories c
    JOIN parts p ON p.category_id = c.id
    GROUP BY c.id
    ORDER BY c.sort_order, c.name_en
  `).all();
}

export function createPart(input) {
  const db = getDb();
  const stmt = db.prepare(`
    INSERT INTO parts
      (sku, name_en, name_tg, description_en, description_tg,
       category_id, unit, cost_price, sale_price,
       quantity_on_hand, reorder_level, location, barcode, active)
    VALUES
      (@sku, @name_en, @name_tg, @description_en, @description_tg,
       @category_id, @unit, @cost_price, @sale_price,
       @quantity_on_hand, @reorder_level, @location, @barcode, @active)
  `);
  const result = stmt.run(normalizePart(input));
  return result.lastInsertRowid;
}

export function updatePart(id, input) {
  const db = getDb();
  const stmt = db.prepare(`
    UPDATE parts SET
      sku             = @sku,
      name_en         = @name_en,
      name_tg         = @name_tg,
      description_en  = @description_en,
      description_tg  = @description_tg,
      category_id     = @category_id,
      unit            = @unit,
      cost_price      = @cost_price,
      sale_price      = @sale_price,
      reorder_level   = @reorder_level,
      location        = @location,
      barcode         = @barcode,
      active          = @active,
      updated_at      = datetime('now')
    WHERE id = @id
  `);
  // Note: quantity_on_hand is intentionally NOT editable here — it changes
  // only through stock_movements.
  stmt.run({ ...normalizePart(input), id });
}

function normalizePart(p) {
  return {
    sku:             (p.sku || '').trim(),
    name_en:         (p.name_en || '').trim(),
    name_tg:         (p.name_tg || '').trim(),
    description_en:  p.description_en?.trim() || null,
    description_tg:  p.description_tg?.trim() || null,
    category_id:     p.category_id ? Number(p.category_id) : null,
    unit:            (p.unit || 'pcs').trim(),
    cost_price:      toDirams(p.cost_price),
    sale_price:      toDirams(p.sale_price),
    quantity_on_hand: Number.isFinite(Number(p.quantity_on_hand)) ? Number(p.quantity_on_hand) : 0,
    reorder_level:   Number.isFinite(Number(p.reorder_level)) ? Number(p.reorder_level) : 0,
    location:        p.location?.trim() || null,
    barcode:         p.barcode?.trim() || null,
    active:          p.active === false || p.active === '0' || p.active === 'false' ? 0 : 1
  };
}

// Accepts somoni-as-string (e.g. "12.50") and returns INTEGER dirams.
function toDirams(value) {
  if (value === '' || value == null) return 0;
  const num = typeof value === 'number' ? value : Number(String(value).replace(',', '.'));
  if (!Number.isFinite(num)) return 0;
  return Math.round(num * 100);
}

export function lowStockParts(limit = 10) {
  return getDb().prepare(`
    SELECT * FROM parts
    WHERE active = 1 AND quantity_on_hand <= reorder_level
    ORDER BY (quantity_on_hand - reorder_level) ASC, sku ASC
    LIMIT ?
  `).all(limit);
}
