'use strict';

const sql = require('mssql');
const { qname, inspectTables, requireColumns } = require('../softrestaurantIntrospection');
const { commandError } = require('../commandHandlers/schemas');
const { createMapper, schemaMismatch } = require('./baseMapper');

async function validate(payload = {}) {
  const productId = payload.product_id || payload.external_product_id || payload.idproducto || payload.idinsumospresentaciones;
  const warehouseId = payload.warehouse_id || payload.idalmacen;
  const quantity = Number(payload.quantity || payload.cantidad);
  const reason = String(payload.reason || payload.motivo || 'Merma registrada desde ARKHON Cloud').trim();
  if (!productId) throw commandError('invalid_payload', 'product_id requerido');
  if (!Number.isFinite(quantity) || quantity <= 0) throw commandError('invalid_payload', 'quantity debe ser mayor a cero');
  if (!reason) throw commandError('invalid_payload', 'reason requerido');
  return {
    productId: String(productId).trim(),
    warehouseId: warehouseId ? String(warehouseId).trim() : null,
    quantity,
    reason: reason.slice(0, 500),
    photoMediaId: payload.photo_media_id || null,
    dry_run: payload.dry_run !== false,
  };
}

async function inspect(pool) {
  return inspectTables(pool, {
    movtosalmacen: ['fecha', 'idalmacen', 'idinsumospresentaciones', 'cantidad', 'idconcepto'],
    almacen: ['idalmacen', 'nombre'],
    insumospresentaciones: ['idinsumospresentaciones', 'descripcion', 'idinsumo'],
    desperdicios: ['cantidad', 'idproducto', 'idinsumo', 'fecha'],
  });
}

async function validateReferences(pool, payload) {
  const out = {};
  const product = await pool.request()
    .input('id', sql.NVarChar(80), payload.productId)
    .query(`SELECT TOP 1 idinsumospresentaciones, idinsumo, descripcion FROM ${qname('insumospresentaciones')} WHERE idinsumospresentaciones=@id`);
  if (!product.recordset.length) throw commandError('inventory_item_not_found', `Presentacion/insumo ${payload.productId} no encontrado`);
  out.product = product.recordset[0];

  if (payload.warehouseId) {
    const warehouse = await pool.request()
      .input('id', sql.NVarChar(80), payload.warehouseId)
      .query(`SELECT TOP 1 idalmacen, nombre FROM ${qname('almacen')} WHERE idalmacen=@id`);
    if (!warehouse.recordset.length) throw commandError('warehouse_not_found', `Almacen ${payload.warehouseId} no encontrado`);
    out.warehouse = warehouse.recordset[0];
  }
  return out;
}

async function dryRun({ payload, pool }) {
  const metadata = await inspect(pool);
  const errors = [
    ...requireColumns(metadata, 'movtosalmacen', ['fecha', 'idalmacen', 'idinsumospresentaciones', 'cantidad']),
    ...requireColumns(metadata, 'insumospresentaciones', ['idinsumospresentaciones']),
  ];
  if (errors.length) schemaMismatch(errors);
  const references = await validateReferences(pool, payload);
  const movement = {
    idalmacen: payload.warehouseId,
    idinsumospresentaciones: payload.productId,
    cantidad: -Math.abs(payload.quantity),
    reason: payload.reason,
    photo_media_id: payload.photoMediaId,
  };
  return {
    ok: true,
    dry_run: true,
    entity_type: 'inventory_waste',
    entity_id: `${payload.warehouseId || 'almacen'}:${payload.productId}`,
    planned_movement: movement,
    references,
  };
}

async function execute() {
  throw commandError(
    'write_not_enabled',
    'CREATE_INVENTORY_WASTE real requiere validar idconcepto y semantica de movtosalmacen en base piloto'
  );
}

const mapper = createMapper({ commandType: 'CREATE_INVENTORY_WASTE', validate, dryRun, execute });

module.exports = { createInventoryWaste: mapper.run, mapper, validate, dryRun, execute, inspect };
