














(function () {
  var React = window.React;
  var h = React.createElement;
  var useState = React.useState;
  var useEffect = React.useEffect;

  /* QUÉ COMBINACIONES EXISTEN lo decide el SERVIDOR y viaja en `data.grilla`. Acá vivían tres
     listas propias —tipos, rangos y jornadas— que eran una segunda definición de la misma grilla,
     el defecto que este sistema ya pagó tres veces (permisos en dos lugares, catálogo de roles en
     tres, tramos del KPI). Con la lista propia, Rosario seguía ofreciendo CHASIS LIVIANO y CHASIS
     PESADO —que BRAINS no opera— aunque el servidor ya no los contara: la tabla mostraba cuatro
     celdas que nadie va a llenar nunca.

     Lo que SÍ queda acá son los NOMBRES para mostrar: eso es presentación, no definición. Si el
     servidor manda una clave que no está en la tabla, se muestra la clave cruda en vez de esconder
     la columna. */
  var NOMBRE_DIM = {
    '0_50': '0 a 50 km', '51_100': '51 a 100 km', '101_150': '101 a 150 km', 'MAS_150': 'Más de 150 km',
    media: 'Media jornada', completa: 'Jornada completa'
  };
  var dimsDe = function (data, ambito) {
    var g = (data && data.grilla && data.grilla[ambito]) || null;
    if (!g) return [];
    return (g.valores || []).map(function (v) { return { clave: v, nombre: NOMBRE_DIM[v] || v }; });
  };
  var tiposDe = function (data, ambito) {
    var g = (data && data.grilla && data.grilla[ambito]) || null;
    return (g && g.tipos) || [];
  };

  /* Normaliza lo tipeado a un numero parseable. NO se pueden borrar todos los puntos a ciegas: el
     campo se rellena con el valor guardado en formato JS ("365748.06"), asi que hacerlo convertia
     365.748,06 en 36.574.806 — un error de CIEN VECES sobre plata, en una tarifa que el operador
     ni siquiera habia tipeado. Lo encontro el arnes, no la lectura.
     La regla: si hay coma, es formato es-AR (punto = miles, coma = decimales). Si no hay coma, se
     deja como esta, que es como lo escribe el propio campo. */
  var normalizarMonto = function (v) {
    var s = String(v == null ? '' : v).trim();
    if (s.indexOf(',') >= 0) return s.replace(/\./g, '').replace(',', '.');
    return s;
  };

  var money = function (n) {
    if (n == null || !isFinite(n)) return '—';
    return '$' + Number(n).toLocaleString('es-AR', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
  };

  function TarifasMeli(props) {
    var ui = window.CR.ui;
    var dState = useState(null); var data = dState[0], setData = dState[1];
    var eState = useState(''); var error = eState[0], setError = eState[1];
    var okState = useState(''); var ok = okState[0], setOk = okState[1];
    var bState = useState(false); var busy = bState[0], setBusy = bState[1];
    /* Ediciones pendientes, por clave. Se acumulan y se guardan juntas con UNA fecha de vigencia:
       la adecuación de MELI cambia todo el cuadro de una vez, no tarifa por tarifa. */
    var edState = useState({}); var edits = edState[0], setEdits = edState[1];
    var vState = useState(''); var vigencia = vState[0], setVigencia = vState[1];
    var hState = useState(null); var historial = hState[0], setHistorial = hState[1];


    var pfState = useState({ porcentaje: '', motivo: '', vigenteDesde: '', ambito: '', tipoUnidad: '', dimension: '' });
    var pctForm = pfState[0], setPctForm = pfState[1];
    /* `cambiosPct` y no `cambios`: mas abajo ya hay un `var cambios = pendientes().length` que
       cuenta las celdas editadas sin guardar. Dos cosas distintas con el mismo nombre en la misma
       funcion es como se escriben los bugs que despues cuesta ver. */
    var cbState = useState([]); var cambiosPct = cbState[0], setCambiosPct = cbState[1];

    function cargar() {
      setBusy(true);
      return window.CR.backend.tarifasMeli()
        .then(function (d) { setData(d); setError(''); })
        .catch(function (e) { setError((e && e.message) || 'No pude traer las tarifas.'); setData(null); })
        .then(function () { setBusy(false); });
    }
    useEffect(function () { cargar(); traerCambios(); }, []);

    var clave = function (ambito, tipo, dim) { return ambito + '|' + tipo + '|' + dim; };

    /* El monto que se muestra en cada celda: la edición pendiente si la hay, si no la guardada. */
    function montoDe(ambito, tipo, dim) {
      var k = clave(ambito, tipo, dim);
      if (Object.prototype.hasOwnProperty.call(edits, k)) return edits[k];
      var lista = ambito === 'BUENOS_AIRES' ? ((data && data.buenosAires) || []) : ((data && data.rosario) || []);
      var f = lista.filter(function (x) {
        return x.tipoUnidad === tipo && (ambito === 'BUENOS_AIRES' ? x.rangoKm === dim : x.jornada === dim);
      })[0];
      return f ? String(f.monto) : '';
    }
    var guardada = function (ambito, tipo, dim) {
      var lista = ambito === 'BUENOS_AIRES' ? ((data && data.buenosAires) || []) : ((data && data.rosario) || []);
      return lista.filter(function (x) {
        return x.tipoUnidad === tipo && (ambito === 'BUENOS_AIRES' ? x.rangoKm === dim : x.jornada === dim);
      })[0] || null;
    };
    function editar(ambito, tipo, dim, valor) {
      var n = Object.assign({}, edits);
      n[clave(ambito, tipo, dim)] = valor;
      setEdits(n);
    }

    /* Sólo se mandan las que CAMBIARON de verdad. Mandar el cuadro entero haría que el repo las
       cuente como "sin cambio", pero igual son 24 idas a la base por nada — y peor: un error de
       tipeo en una celda que nadie tocó viajaría igual. */
    function pendientes() {
      var out = [];
      Object.keys(edits).forEach(function (k) {
        var p = k.split('|'), ambito = p[0], tipo = p[1], dim = p[2];
        var crudo = normalizarMonto(edits[k]);
        var monto = Number(crudo);
        var actual = guardada(ambito, tipo, dim);
        if (crudo === '' || !isFinite(monto) || monto < 0) return;
        if (actual && Number(actual.monto) === monto) return;
        var fila = { ambito: ambito, tipoUnidad: tipo, monto: monto };
        if (ambito === 'BUENOS_AIRES') fila.rangoKm = dim; else fila.jornada = dim;
        out.push(fila);
      });
      return out;
    }
    /* Lo que se tipeó pero NO se puede guardar. Se cuenta y se avisa: si no, el operador aprieta
       Guardar, ve "3 tarifas cargadas" y no se entera de que la cuarta se descartó por un typo. */
    function invalidas() {
      return Object.keys(edits).filter(function (k) {
        var crudo = normalizarMonto(edits[k]);
        if (crudo === '') return false;
        var n = Number(crudo);
        return !isFinite(n) || n < 0;
      }).length;
    }





    function aplicarPorcentaje() {
      var pct = Number(String(pctForm.porcentaje).replace(',', '.'));
      if (!isFinite(pct) || pct === 0) { setError('Poné un porcentaje distinto de cero.'); return; }
      if (!String(pctForm.motivo || '').trim()) {
        setError('Escribí el motivo del cambio: es lo que se va a leer dentro de seis meses.');
        return;
      }
      if (!pctForm.vigenteDesde) { setError('Poné desde cuándo rige el cambio.'); return; }
      setBusy(true); setError(''); setOk('');
      window.CR.backend.cambiarTarifasMeliPorcentaje({
        porcentaje: pct, vigenteDesde: pctForm.vigenteDesde, motivo: pctForm.motivo,
        ambito: pctForm.ambito || null, tipoUnidad: pctForm.tipoUnidad || null,
        dimension: pctForm.dimension || null
      }).then(function (r) {
        var c = (r && r.cambio) || {};
        setOk('Cambio aplicado: ' + c.filas + ' tarifa(s) al ' + (pct > 0 ? '+' : '') + pct
          + '%, desde ' + c.vigenteDesde + '.');
        setPctForm(Object.assign({}, pctForm, { porcentaje: '', motivo: '' }));
        setBusy(false);
        cargar(); traerCambios();
      }).catch(function (e) { setError(e.message); setBusy(false); });
    }
    function traerCambios() {
      /* La guarda no es paranoia: el front se sirve con cache-bust por archivo, asi que un navegador
         puede quedarse con un `lib/backend.js` viejo mientras la pantalla ya es nueva. Sin esto, la
         pantalla ENTERA no monta por un historial que es lo menos importante que muestra. */
      if (!window.CR.backend || typeof window.CR.backend.cambiosTarifasMeli !== 'function') return;
      window.CR.backend.cambiosTarifasMeli().then(setCambiosPct).catch(function () {});
    }

    function guardar() {
      var filas = pendientes();
      if (!filas.length) { setError('No hay ningún cambio para guardar.'); return; }
      if (!/^\d{4}-\d{2}-\d{2}$/.test(vigencia)) {
        setError('Poné desde cuándo rige el cuadro nuevo. Sin fecha no se puede aplicar a un período.');
        return;
      }
      setBusy(true); setError(''); setOk('');
      window.CR.backend.guardarTarifasMeli(filas, vigencia, null)
        .then(function (r) {
          setEdits({});
          setOk('Listo: ' + r.nuevas + ' tarifa(s) nueva(s), ' + r.cerradas + ' vigencia(s) cerrada(s)'
            + (r.sinCambio ? ', ' + r.sinCambio + ' sin cambio' : '')
            + (r.rechazadas ? ' · ' + r.rechazadas + ' rechazada(s) por formato' : '') + '.');
          return cargar();
        })
        .catch(function (e) { setError((e && e.message) || 'No pude guardar.'); setBusy(false); });
    }

    function verHistorial(ambito, tipo, dim) {
      var q = { ambito: ambito, tipoUnidad: tipo };
      if (ambito === 'BUENOS_AIRES') q.rangoKm = dim; else q.jornada = dim;
      window.CR.backend.historialTarifaMeli(q)
        .then(function (hs) { setHistorial({ titulo: tipo + ' · ' + dim, filas: hs }); })
        .catch(function (e) { setError((e && e.message) || 'No pude traer el historial.'); });
    }

    function grilla(ambito, titulo, ayuda) {
      var dims = dimsDe(data, ambito);
      var tipos = tiposDe(data, ambito);
      var faltan = data ? (ambito === 'BUENOS_AIRES' ? data.faltan.buenosAires : data.faltan.rosario) : 0;
      /* `grilla-tarifas` marca las DOS cards del cuadro. No es decorativo: el arnes necesita poder
         nombrar las grillas en vez de contar todas las tablas de la pantalla, que es como el
         historial de cambios (una tercera tabla) rompio nueve aserciones sin tocar el cuadro. */
      return h(ui.Card, { title: titulo, className: 'grilla-tarifas' },
        h('p', { className: 'muted' }, ayuda),
        /* CONTAR lo que falta. Una grilla con agujeros no se nota mirándola: se ve una tabla llena
           de números y nadie sabe que hay combinaciones sin tarifa, que van a facturar mal. */
        faltan > 0 ? h('div', { className: 'alerta alerta--media', role: 'status' },
          h('b', null, 'Faltan ' + faltan + ' tarifa(s) por cargar'),
          ' — las rutas de esas combinaciones no se pueden facturar hasta que estén.') : null,
        h('div', { className: 'tablewrap' },
          h('table', { className: 'tbl' },
            h('thead', null, h('tr', null,
              h('th', null, 'Tipo de unidad'),
              dims.map(function (d) { return h('th', { key: d.clave, style: { textAlign: 'right' } }, d.nombre); }))),
            h('tbody', null, tipos.map(function (tipo) {
              return h('tr', { key: tipo },
                h('td', null, h('b', null, tipo)),
                dims.map(function (d) {
                  var g = guardada(ambito, tipo, d.clave);
                  var k = clave(ambito, tipo, d.clave);
                  var tocada = Object.prototype.hasOwnProperty.call(edits, k);
                  return h('td', { key: d.clave, style: { textAlign: 'right', minWidth: 150 } },













                    g
                      ? h('div', { className: 'tarifa-cerrada',
                          'aria-label': 'Tarifa ' + tipo + ' ' + d.nombre + ' (cerrada)',
                          style: { fontWeight: 600, fontVariantNumeric: 'tabular-nums' } },
                          money(g.monto))
                      : h(ui.Input, {
                          value: montoDe(ambito, tipo, d.clave), disabled: busy,
                          placeholder: 'sin cargar',
                          'aria-label': 'Tarifa ' + tipo + ' ' + d.nombre,
                          onChange: function (v) { editar(ambito, tipo, d.clave, v); }
                        }),
                    /* Debajo del campo, el valor VIGENTE y desde cuándo. Sin esto, editar una celda
                       borra de la vista lo que estaba cobrando, y no hay con qué comparar. */
                    h('div', { className: 'muted', style: { fontSize: 11, marginTop: 2 } },
                      g ? h('span', null,
                            tocada ? h('span', null, 'vigente: ', money(g.monto), ' · ') : null,
                            'desde ', g.desde,
                            ' · ', h('button', {
                              type: 'button', className: 'btn btn--ghost btn--sm',
                              style: { padding: '0 4px', fontSize: 11 },
                              onClick: function () { verHistorial(ambito, tipo, d.clave); }
                            }, 'historial'))
                        : h('span', { className: 'badge badge--warn', style: { fontSize: 10 } }, 'sin cargar')));
                }));
            })))));
    }

    if (!data && busy) return h(ui.Card, { title: 'Tarifas de Mercado Libre' }, h('p', { className: 'muted' }, 'Cargando…'));

    var cambios = pendientes().length;
    var malas = invalidas();
    return h('div', null,
      h(ui.Page, {
        title: 'Tarifas de Mercado Libre',
        subtitle: 'Lo que Mercado Libre nos paga por servicio. No confundir con Tarifa de proveedores, que es lo que le pagamos al chofer.'
      }),


      h('div', { className: 'alerta alerta--baja', role: 'note' },
        h('b', null, 'Sólo gerencia.'), ' Estas tarifas son la facturación del negocio. El equipo operativo no las ve.'),
      error ? h('div', { className: 'alerta alerta--alta', role: 'alert' }, error) : null,
      ok ? h('div', { className: 'alerta alerta--baja', role: 'status' }, ok) : null,

      grilla('BUENOS_AIRES', 'Buenos Aires',
        'La tarifa depende del tipo de unidad y de los kilómetros de la ruta.'),
      grilla('ROSARIO', 'Rosario',
        'Acá la tarifa va por horas de jornada. Hoy se toma siempre media jornada, porque el 99% de las rutas lo son — la de jornada completa se guarda para el 1% restante. Sólo figuran camioneta y chasis: BRAINS no opera chasis liviano ni chasis pesado en esta plaza.'),

      /* Una tarifa cargada fuera de la grilla es plata que alguien cargó. Si la regla de negocio
         cambia y la escondemos, nadie sabe que sigue ahí — ni que se puede estar facturando con
         ella. Se muestra, marcada, en vez de desaparecer de la pantalla. */
      (data && data.fueraDeGrilla && data.fueraDeGrilla.length)
        ? h('div', { className: 'alerta alerta--media', role: 'status' },
            h('b', null, data.fueraDeGrilla.length + ' tarifa(s) cargada(s) fuera de la grilla actual'),
            ' — quedaron de una combinación que ya no se usa: ',
            data.fueraDeGrilla.map(function (x) {
              return x.ambito + ' · ' + x.tipoUnidad + ' · ' + (x.rangoKm || x.jornada);
            }).join(' | '),
            '. Siguen vigentes hasta que se cierren.')
        : null,

      /* CAMBIOS POR PORCENTAJE. Va ARRIBA de la carga manual a proposito: desde el 26/08 editar el
         precio de una tarifa que ya rige esta bloqueado del lado del servidor, asi que este es el
         camino normal y el de abajo quedo para completar combinaciones que todavia no existen. */
      h(ui.Card, { title: 'Cambios por porcentaje' },
        h('p', { className: 'muted' },
          'Un aumento o descuento no pisa la tarifa: cierra la vigente el día previo y abre una nueva. ',
          'Dejá el alcance vacío para aplicarlo a TODAS las tarifas vigentes.'),
        h(ui.Toolbar, null,
          h(ui.Field, { label: '% de cambio' },
            h(ui.Input, { value: pctForm.porcentaje, disabled: busy, placeholder: 'ej: 25 o -10',
              'aria-label': 'Porcentaje de cambio',
              onChange: function (v) { setPctForm(Object.assign({}, pctForm, { porcentaje: v })); } })),
          h(ui.Field, { label: 'Rige desde' },
            h(ui.Input, { type: 'date', value: pctForm.vigenteDesde, disabled: busy,
              'aria-label': 'Fecha desde la que rige el cambio',
              onChange: function (v) { setPctForm(Object.assign({}, pctForm, { vigenteDesde: v })); } })),
          h(ui.Field, { label: 'Ámbito' },
            h(ui.Select, { value: pctForm.ambito, placeholder: 'Todos', 'aria-label': 'Ámbito',
              options: [{ value: '', label: 'Todos' }, { value: 'BUENOS_AIRES', label: 'Buenos Aires' },
                { value: 'ROSARIO', label: 'Rosario' }],
              onChange: function (v) { setPctForm(Object.assign({}, pctForm, { ambito: v })); } })),
          h(ui.Field, { label: 'Tipo de unidad' },
            h(ui.Input, { value: pctForm.tipoUnidad, disabled: busy, placeholder: 'Todos',
              'aria-label': 'Tipo de unidad',
              onChange: function (v) { setPctForm(Object.assign({}, pctForm, { tipoUnidad: v })); } })),
          h(ui.Field, { label: 'Rango / jornada' },
            h(ui.Input, { value: pctForm.dimension, disabled: busy, placeholder: 'Todos',
              'aria-label': 'Rango de km o jornada',
              onChange: function (v) { setPctForm(Object.assign({}, pctForm, { dimension: v })); } }))),
        h(ui.Field, { label: 'Motivo (obligatorio)' },
          h(ui.Input, { value: pctForm.motivo, disabled: busy,
            placeholder: 'ej: aumento semestral acordado con MELI',
            'aria-label': 'Motivo del cambio',
            onChange: function (v) { setPctForm(Object.assign({}, pctForm, { motivo: v })); } })),
        h(ui.Toolbar, null,
          h('div', { className: 'spacer' }),
          h(ui.Button, { variant: 'primary', disabled: busy, onClick: aplicarPorcentaje },
            busy ? 'Aplicando…' : 'Aplicar cambio'))),



      h(ui.Card, { title: 'Historial de cambios de tarifa', className: 'historial-cambios' },
        cambiosPct.length
          ? h(ui.DataTable, {
              rows: cambiosPct, rowKey: 'id',
              columns: [
                { key: 'aplicadoEn', label: 'Fecha',
                  render: function (x) { return String(x.aplicadoEn || '').slice(0, 16).replace('T', ' '); } },
                { key: 'aplicadoPor', label: 'Usuario', render: function (x) { return x.aplicadoPor || '—'; } },
                { key: 'porcentaje', label: '%', align: 'right',
                  render: function (x) { return (x.porcentaje > 0 ? '+' : '') + x.porcentaje + '%'; } },
                { key: 'alcance', label: 'Alcance', render: function (x) {
                  var partes = [x.ambito, x.tipoUnidad, x.dimension].filter(Boolean);
                  return partes.length ? partes.join(' · ') : 'Todas';
                } },
                { key: 'vigenteDesde', label: 'Rige desde' },
                { key: 'filas', label: 'Tarifas', align: 'right' },
                { key: 'motivo', label: 'Motivo' }
              ]
            })
          : h('p', { className: 'muted' }, 'Todavía no se aplicó ningún cambio por porcentaje.')),

      h(ui.Card, { title: 'Guardar los cambios' },
        h('p', { className: 'muted' },
          'Cargar una tarifa no pisa la anterior: la cierra el día previo. Por eso una quincena ya ',
          'facturada sigue dando el número que dio, y el historial deja ver qué se cobraba en cada mes.'),
        h(ui.Toolbar, null,
          h(ui.Field, { label: 'Rige desde' },
            h(ui.Input, { type: 'date', value: vigencia, disabled: busy, onChange: setVigencia,
              'aria-label': 'Fecha desde la que rige el cuadro nuevo' })),
          h('div', { className: 'spacer' }),
          malas > 0 ? h('span', { className: 'badge badge--danger' },
            malas + ' celda(s) con un valor que no es un número') : null,
          h('span', { className: 'muted' }, cambios ? (cambios + ' cambio(s) para guardar') : 'Sin cambios'),
          h(ui.Button, { variant: 'primary', disabled: busy || !cambios, onClick: guardar },
            busy ? 'Guardando…' : 'Guardar cambios'))),

      /* `open: true` no es decorativo: `Modal` devuelve null sin esa prop. Lo cazo el arnes —
         el boton existia, se clickeaba, y no aparecia nada. */
      historial ? h(ui.Modal, { open: true, title: 'Historial · ' + historial.titulo, onClose: function () { setHistorial(null); } },
        historial.filas.length
          ? h(ui.DataTable, {
              rows: historial.filas, rowKey: 'desde',
              columns: [
                { key: 'monto', label: 'Tarifa', align: 'right', render: function (x) { return money(x.monto); } },
                { key: 'desde', label: 'Desde' },
                { key: 'hasta', label: 'Hasta', render: function (x) { return x.hasta || 'vigente'; } },
                { key: 'origen', label: 'Origen' },
                { key: 'cargada', label: 'Cargada' }
              ]
            })
          : h('p', { className: 'muted' }, 'Todavía no hay historial para esta combinación.')) : null);
  }

  window.CR.screens = window.CR.screens || {};
  window.CR.screens.TarifasMeli = TarifasMeli;
})();
