/* Módulo 3 — Asignación v4. Sobre v3 (wizard + gate + FX) agrega:
   FIX1 unicidad por jornada: un vehículo/chofer asignado a una ruta se DESHABILITA en el selector de las demás.
   FIX2 alta de vehículo en el momento: en "sin cubrir" abre un form (patente, capacidad, chofer), lo crea, lo
        asigna a la zona y recalcula la cobertura.
   FIX3 aviso DEMO: al confirmar la programación dispara un aviso al celular demo (OpenWA si está, si no wa.me).
   window.CR.screens.Asignacion */
(function () {
  var React = window.React;
  var ui = window.CR.ui, store = window.CR.store, K = window.CR.const, eng = window.CR.engine;
  var h = React.createElement;

  function Asignacion() {
    window.CR.useStore();
    var rutas = store.list('rutas');
    var vehiculos = store.list('vehiculos');
    var choferes = store.list('choferes');
    var cById = {}; choferes.forEach(function (c) { cById[c.id] = c; });
    var vById = {}; vehiculos.forEach(function (v) { vById[v.id] = v; });
    var rById = {}; rutas.forEach(function (r) { rById[r.id] = r; });
    var cargaState = React.useState(parseInt(localStorage.getItem('cr.cargaObjetivo') || '75', 10));
    var carga = cargaState[0], setCarga = cargaState[1];
    var confState = React.useState(false); var confirming = confState[0], setConfirming = confState[1];
    var okState = React.useState(false); var success = okState[0], setSuccess = okState[1];
    var avisoState = React.useState(null); var demoAviso = avisoState[0], setDemoAviso = avisoState[1];
    var altaState = React.useState(null); var alta = altaState[0], setAlta = altaState[1];
    function setA(patch) { setAlta(Object.assign({}, alta, patch)); }

    // FIX1 — qué recurso está usado y por qué ruta (unicidad por jornada)
    var usedCho = {}, usedVeh = {};
    rutas.forEach(function (r) { if (r.choferId) usedCho[r.choferId] = r.id; if (r.vehiculoId) usedVeh[r.vehiculoId] = r.id; });
    function choferOptsFor(r) {
      return choferes.filter(function (c) { return c.estado === 'disponible'; })
        .sort(function (a, b) { return b.desempeno - a.desempeno; })
        .map(function (c) {
          var en = usedCho[c.id]; var dis = !!(en && en !== r.id);
          return { value: c.id, disabled: dis,
            label: c.nombre + ' (' + c.desempeno + (c.esAgencia ? ', agencia' : '') + ')' + (dis ? ' · ya en ' + (rById[en] ? rById[en].numero : '') : '') };
        });
    }
    function vehOptsFor(r) {
      return vehiculos.filter(function (v) { return v.estado !== 'taller'; })
        .map(function (v) {
          var en = usedVeh[v.id]; var dis = !!(en && en !== r.id);
          return { value: v.id, disabled: dis,
            label: v.patente + ' · ' + K.labelTipo(v.tipoUnidad) + ' (cap ' + K.capacidad(v.tipoUnidad) + ')' + (dis ? ' · ya en ' + (rById[en] ? rById[en].numero : '') : '') };
        });
    }

    function reoptimizar(val) {
      localStorage.setItem('cr.cargaObjetivo', String(val));
      var be = window.CR.backend && window.CR.backend.enabled;
      if (be) { window.CR.backend.reoptimizar(val).catch(function () {}); return; }
      var zonas = window.CR.aggregate.porZona(store.list('pedidos'));
      if (!zonas.length) return;
      var r = eng.asignarPorCapacidad(zonas, vehiculos, choferes, { cargaObjetivo: val });
      store.bulkSet('rutas', eng.aplanar(r)); window.CR._leftovers = [];
    }
    function correr() {
      var be = window.CR.backend && window.CR.backend.enabled;
      if (be) { window.CR.backend.reoptimizar(carga).catch(function () { alert('No pude re-optimizar por el backend.'); }); return; }
      var zonas = window.CR.aggregate.porZona(store.list('pedidos'));
      if (!zonas.length) { alert('Primero importá pedidos (módulo Importar).'); return; }
      var r = eng.asignarPorCapacidad(zonas, vehiculos, choferes, { cargaObjetivo: carga });
      store.bulkSet('rutas', eng.aplanar(r)); window.CR._leftovers = [];
    }
    function setRuta(id, patch) {
      var r = store.get('rutas', id); if (!r) return;
      store.upsert('rutas', Object.assign({}, r, patch));
    }

    // ---- ASISTENTE: auto-fix por discrepancia ----
    function resolverDisc(d) {
      var a = d.accion || {};
      if (a.tipo === 'asignarChofer') {
        var ru = store.get('rutas', a.rutaId); if (!ru) return;
        var c = eng.choferDisponible(store.list('rutas'), choferes, ru.zona);
        if (c) setRuta(ru.id, { choferId: c.id, banda: eng.banda(c.desempeno), estado: ru.estado === 'sin_asignar' ? 'asignada' : ru.estado });
        return;
      }
      if (a.tipo === 'asignarVehiculo') {
        var rv = store.get('rutas', a.rutaId); if (!rv) return;
        var v = eng.vehiculoDisponible(store.list('rutas'), vehiculos, rv.paquetes);
        if (v) setRuta(rv.id, { vehiculoId: v.id, tipoUnidad: v.tipoUnidad, capacidad: K.capacidad(v.tipoUnidad), estado: rv.estado === 'sin_asignar' ? 'asignada' : rv.estado });
        return;
      }
      if (a.tipo === 'rebalancearZona') {
        var nuevas = eng.rebalancearZona(store.list('rutas'), vehiculos, choferes, a.zona, carga);
        store.bulkSet('rutas', nuevas); window.CR._leftovers = [];
      }
    }
    function resolverTodo() {
      var guard = 0, prev = Infinity;
      while (guard++ < 40) {
        var b = eng.bloqueantes(store.list('rutas'), []);
        if (!b.length) break;
        if (b.length >= prev) break;
        prev = b.length;
        resolverDisc(b[0]);
      }
    }
    function puedeResolver(d) {
      var a = d.accion || {}, rs = store.list('rutas');
      if (a.tipo === 'asignarChofer') return !!eng.choferDisponible(rs, choferes, d.zona);
      if (a.tipo === 'asignarVehiculo') return !!eng.vehiculoDisponible(rs, vehiculos, d.paquetes);
      if (a.tipo === 'rebalancearZona') {
        var enZ = rs.filter(function (r) { return r.zona === d.zona; });
        var totalP = enZ.reduce(function (s, r) { return s + (r.paquetes || 0); }, 0);
        var capZ = enZ.reduce(function (s, r) { return s + (r.vehiculoId && r.choferId ? r.capacidad : 0); }, 0);
        if (capZ >= totalP) return true;
        return !!(eng.vehiculoDisponible(rs, vehiculos, 0) && eng.choferDisponible(rs, choferes, d.zona));
      }
      return false;
    }

    // FIX2 — alta de vehículo en el momento
    function abrirAlta(zona) {
      var libres = choferes.filter(function (c) { return c.estado === 'disponible' && !usedCho[c.id]; });
      setAlta({ zona: zona, patente: '', tipoUnidad: 'CHE', choferSel: libres.length ? libres[0].id : '__nuevo__', nombre: '', desempeno: 80 });
    }
    function crearVehiculoYAsignar() {
      var a = alta; if (!a) return;
      var pat = (a.patente || '').trim().toUpperCase();
      if (!pat) return;
      var vid = 'v_' + Math.random().toString(36).slice(2, 8);
      var v = { id: vid, tipoUnidad: a.tipoUnidad, patente: pat, antiguedad: 0, estado: 'activo' };
      store.upsert('vehiculos', v);
      if (window.CR.backend && window.CR.backend.enabled) window.CR.backend.crearVehiculo(v);
      var cid;
      if (a.choferSel === '__nuevo__' || !a.choferSel) {
        cid = 'c_' + Math.random().toString(36).slice(2, 8);
        var nombre = (a.nombre || '').trim() || ('Chofer ' + pat);
        var c = { id: cid, nombre: nombre, zonaOrigen: a.zona, desempeno: parseInt(a.desempeno, 10) || 80, telefono: '', esAgencia: false, contactoAgencia: '', estado: 'disponible', ack: 'pendiente' };
        store.upsert('choferes', c);
        if (window.CR.backend && window.CR.backend.enabled) window.CR.backend.crearChofer(c);
      } else {
        cid = a.choferSel;
      }
      // asignar: el nuevo vehículo+chofer SÍ o SÍ a esta zona, y rebalancear el resto -> recalcula cobertura
      var nuevas = eng.rebalancearZona(store.list('rutas'), store.list('vehiculos'), store.list('choferes'), a.zona, carga, { vehId: vid, choId: cid });
      store.bulkSet('rutas', nuevas); window.CR._leftovers = [];
      setAlta(null);
    }

    function confirmar() { if (bloq.length) return; setConfirming(true); }
    function trasConfirmar() {
      store.list('rutas').forEach(function (r) { if (r.estado === 'asignada') store.upsert('rutas', Object.assign({}, r, { estado: 'confirmada' })); });
      // FIX3 — aviso DEMO al celular al confirmar la asignación
      var k = window.CR.kpis.calcular({ rutas: store.list('rutas'), choferes: choferes, vehiculos: vehiculos, pedidos: store.list('pedidos') });
      var msg = 'CRÁNEO Rutas — Programación confirmada (' + K.hoy() + '). ' + k.camiones + ' camiones · ' + k.paquetesAsignados + ' paquetes · cobertura ' + k.cobertura + '%.';
      var av = window.CR.whatsapp.avisoConfirmacion(msg);
      if (av && av.promesa) av.promesa.catch(function () {});
      setDemoAviso(av ? { telefono: av.telefono, link: av.link, modo: av.modo } : null);
      setConfirming(false); setSuccess(true);
    }

    var disc = eng.discrepancias(rutas, []);
    var bloq = disc.filter(function (d) { return d.bloqueante; });
    var asignadas = rutas.filter(function (r) { return r.choferId; }).length;

    if (!rutas.length) {
      return h('div', null, h(ui.Page, { title: 'Asignación' }),
        h(ui.Card, null, h(ui.EmptyState, { title: 'Todavía no hay nada asignado',
          action: h(ui.Button, { variant: 'primary', onClick: function () { window.location.hash = '#/importar'; } }, 'Ir a importar pedidos') },
          'Importá el archivo de pedidos y el sistema asigna los camiones automáticamente.')));
    }

    function esPH(r) { return !r.vehiculoId && !r.choferId; }

    // botones de acción de una discrepancia en el wizard
    function accionBotones(d) {
      var a = d.accion || {};
      if (a.tipo === 'rebalancearZona') {
        var arr = [h(ui.Button, { key: 'add', variant: 'primary', size: 'sm', onClick: function () { abrirAlta(d.zona); } }, '➕ Agregar vehículo')];
        if (puedeResolver(d)) arr.push(h(ui.Button, { key: 'reb', variant: 'ghost', size: 'sm', onClick: function () { resolverDisc(d); } }, 'Rebalancear con flota libre'));
        return arr;
      }
      if (a.tipo === 'asignarChofer') {
        return puedeResolver(d)
          ? [h(ui.Button, { key: 'c', variant: 'primary', size: 'sm', onClick: function () { resolverDisc(d); } }, 'Asignar mejor chofer')]
          : [h('span', { key: 'c0', className: 'badge badge--warn', dot: true }, 'No hay choferes libres — creá uno con ➕ Agregar vehículo')];
      }
      // asignarVehiculo
      return puedeResolver(d)
        ? [h(ui.Button, { key: 'v', variant: 'primary', size: 'sm', onClick: function () { resolverDisc(d); } }, 'Asignar vehículo')]
        : [h(ui.Button, { key: 'va', variant: 'primary', size: 'sm', onClick: function () { abrirAlta(d.zona); } }, '➕ Agregar vehículo')];
    }

    var avisoExtra = demoAviso ? h('div', { style: { display: 'flex', flexDirection: 'column', gap: 8, alignItems: 'center' } },
      h('span', { className: 'appphone' }, '📲 Aviso DEMO → ' + demoAviso.telefono + ' · ' + demoAviso.modo),
      h(ui.Button, { variant: 'ghost', size: 'sm', onClick: function () { window.open(demoAviso.link, '_blank'); } }, 'Abrir WhatsApp del aviso')) : null;

    return h('div', null,
      h(ui.Page, { title: 'Asignación', subtitle: 'Camiones asignados por zona, capacidad (volumetría) y ranking del chofer. Editá y el mapa se actualiza.' }),

      h(ui.LoadingOverlay, { open: confirming, title: 'Confirmando programación',
        steps: ['Validando que no queden discrepancias…', 'Bloqueando las cargas del día…', 'Avisando al celular de la operación…'],
        durationMs: 2000, onDone: trasConfirmar }),
      h(ui.SuccessOverlay, { open: success, title: 'Programación confirmada',
        subtitle: 'Quedó lista para cargar a Mercado Libre. Pasá a Notificar para avisar a los choferes.',
        extra: avisoExtra, ctaLabel: 'Ir a Notificar', onCta: function () { setSuccess(false); window.location.hash = '#/notificar'; }, onClose: function () { setSuccess(false); } }),

      // FIX2 — modal alta de vehículo
      altaModal(),

      h(ui.Toolbar, null,
        h(ui.Button, { variant: 'primary', onClick: correr, icon: '⚙' }, 'Re-asignar automáticamente'),
        h('span', { className: 'badge badge--ok', dot: true }, asignadas + ' camiones asignados'),
        bloq.length ? h('span', { className: 'badge badge--danger', dot: true }, bloq.length + ' discrepancia' + (bloq.length > 1 ? 's' : '')) : h('span', { className: 'badge badge--ok', dot: true }, 'Sin discrepancias'),
        h('div', { className: 'spacer' }),
        h(ui.Button, { variant: 'primary', onClick: confirmar, disabled: bloq.length > 0,
          title: bloq.length ? 'Resolvé las discrepancias para poder confirmar' : 'Confirmar y dejar lista para Mercado Libre' }, 'Confirmar programación')),

      h(ui.Card, null,
        h('div', { style: { display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap' } },
          h('div', { style: { minWidth: 220 } },
            h('div', { style: { fontWeight: 600, fontSize: 13 } }, 'Carga objetivo por camión'),
            h('div', { className: 'muted', style: { fontSize: 12 } }, 'Cuántos paquetes apuntás por unidad (reparte más parejo)')),
          h('input', { type: 'range', className: 'cr-range', min: 40, max: 150, step: 5, value: carga,
            style: { flex: 1, minWidth: 180 },
            onChange: function (e) { setCarga(parseInt(e.target.value, 10)); },
            onMouseUp: function (e) { reoptimizar(parseInt(e.target.value, 10)); },
            onTouchEnd: function (e) { reoptimizar(parseInt(e.target.value, 10)); } }),
          h('span', { className: 'badge badge--info', style: { fontSize: 14, minWidth: 92, justifyContent: 'center' } }, carga + ' paquetes'))),

      bloq.length ? h(ui.Card, { title: 'Asistente — resolvé antes de confirmar' },
        h('div', { className: 'gate' },
          h('span', { className: 'gate-ic' }, '⛔'),
          h('div', null,
            h('h4', null, 'No se puede confirmar: hay ' + bloq.length + ' cosa' + (bloq.length > 1 ? 's' : '') + ' que harían que no se entregue el 100% de los paquetes'),
            h('p', { className: 'muted' }, 'Resolvé cada punto (uno por uno o todo automático). La confirmación se habilita cuando no quede ninguna.'))),
        h('div', { className: 'wiz-prog' },
          h(ui.Button, { variant: 'primary', onClick: resolverTodo, icon: '✨' }, 'Resolver todo automáticamente'),
          h('span', { className: 'muted', style: { fontSize: 13 } }, bloq.length + ' pendiente' + (bloq.length > 1 ? 's' : ''))),
        bloq.map(function (d, i) {
          return h('div', { key: i, className: 'disc disc--alta' },
            h('span', { style: { fontSize: 16 } }, '⚠'),
            h('div', { style: { flex: 1 } },
              h('b', null, d.tipo === 'sobrecarga' ? 'Sobrecarga' : d.tipo === 'sin_cobertura' ? 'Paquetes sin camión' : d.tipo === 'sin_chofer' ? 'Falta chofer' : 'Falta vehículo'),
              h('div', { className: 'muted', style: { fontSize: 13 } }, d.detalle),
              h('div', { className: 'disc__sug' }, '💡 ' + d.sugerencia),
              h('div', { className: 'disc__actions' }, accionBotones(d))));
        })) : h(ui.Card, null,
        h('div', { className: 'disc disc--ok' },
          h('span', { className: 'disc__done' }, '✓ Sin discrepancias — la programación cubre el 100% de los paquetes, podés confirmar.'))),

      h(ui.Card, { title: 'Mapa de asignación', actions: h('span', { className: 'muted', style: { fontSize: 12 } }, 'Zoom con la rueda del mouse · arrastrá para mover') },
        h(window.CR.Mapa, { rutas: rutas, choferes: choferes, vehiculos: vehiculos })),

      ['N', 'O', 'E', 'S'].map(function (z) {
        var arr = rutas.filter(function (r) { return r.zona === z; });
        if (!arr.length) return null;
        return h(ui.Card, { key: z, title: K.labelZona(z) + ' — ' + arr.reduce(function (a, r) { return a + r.paquetes; }, 0) + ' paquetes en ' + arr.length + ' camión(es)' },
          arr.map(function (r) {
            if (esPH(r)) {
              return h('div', { key: r.id, className: 'disc disc--alta', style: { marginTop: 4 } },
                h('span', { style: { fontSize: 16 } }, '⚠'),
                h('div', { style: { flex: 1 } },
                  h('b', null, 'Sin cubrir: ' + r.paquetes + ' paquetes'),
                  h('div', { className: 'muted', style: { fontSize: 13 } }, 'No quedó camión disponible para esta carga.'),
                  h('div', { className: 'disc__actions' },
                    h(ui.Button, { variant: 'primary', size: 'sm', onClick: function () { abrirAlta(z); } }, '➕ Agregar vehículo'),
                    puedeResolver({ accion: { tipo: 'rebalancearZona', zona: z }, zona: z })
                      ? h(ui.Button, { variant: 'ghost', size: 'sm', onClick: function () { resolverDisc({ accion: { tipo: 'rebalancearZona', zona: z } }); } }, 'Rebalancear con flota libre') : null)));
            }
            var over = r.paquetes > r.capacidad;
            var chofer = cById[r.choferId], veh = vById[r.vehiculoId];
            var pct = r.capacidad ? Math.min(100, Math.round(r.paquetes / r.capacidad * 100)) : 0;
            return h('div', { key: r.id, style: { padding: '12px 0', borderBottom: '1px solid var(--border)' } },
              h('div', { style: { display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap', marginBottom: 8 } },
                h(ui.Badge, { color: 'neutral' }, 'Camión ' + r.numero),
                h('b', null, veh ? veh.patente : '—'),
                h('span', { className: 'muted' }, K.labelTipo(r.tipoUnidad)),
                over ? h(ui.Badge, { color: 'danger', dot: true }, 'SOBRECARGA') : h(ui.Badge, { color: 'ok' }, r.estado === 'confirmada' ? 'Confirmada' : 'Asignada')),
              h('div', { style: { display: 'flex', gap: 14, flexWrap: 'wrap', alignItems: 'end' } },
                h(ui.Field, { label: 'Chofer (ranking)', className: 'row-grow' },
                  h(ui.Select, { value: r.choferId || '', placeholder: 'Elegir chofer', options: choferOptsFor(r), onChange: function (v) { setRuta(r.id, { choferId: v, banda: cById[v] ? eng.banda(cById[v].desempeno) : r.banda }); } })),
                h(ui.Field, { label: 'Vehículo' },
                  h(ui.Select, { value: r.vehiculoId || '', placeholder: 'Elegir vehículo', options: vehOptsFor(r), onChange: function (v) { var nv = vById[v]; setRuta(r.id, { vehiculoId: v, tipoUnidad: nv ? nv.tipoUnidad : r.tipoUnidad, capacidad: nv ? K.capacidad(nv.tipoUnidad) : r.capacidad }); } })),
                h(ui.Field, { label: 'Paquetes', className: 'paq' },
                  h(ui.Input, { type: 'number', value: r.paquetes, onChange: function (v) { setRuta(r.id, { paquetes: parseInt(v || '0', 10) || 0 }); } })),
                h(ui.Field, { label: 'Zona' },
                  h(ui.Select, { value: r.zona, options: K.ZONAS.map(function (zz) { return { value: zz.k, label: zz.label }; }), onChange: function (v) { setRuta(r.id, { zona: v }); } }))),
              h('div', { style: { marginTop: 8 } },
                h('div', { style: { display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 3 } },
                  h('span', { className: 'muted' }, chofer ? ('Chofer: ' + chofer.nombre + ' · desemp. ' + chofer.desempeno + (chofer.zonaOrigen === r.zona ? ' · zona propia' : '')) : 'Sin chofer'),
                  h('b', { className: over ? '' : 'muted', style: over ? { color: 'var(--danger)' } : null }, r.paquetes + ' / ' + r.capacidad + ' paquetes (' + pct + '%)')),
                h('div', { className: 'capbar' }, h('span', { className: over ? 'over' : '', style: { width: pct + '%' } }))));
          }));
      }));

    // ---- modal de alta de vehículo (FIX2) ----
    function altaModal() {
      if (!alta) return null;
      var libres = choferes.filter(function (c) { return c.estado === 'disponible' && !usedCho[c.id]; });
      var choferOpts = [{ value: '__nuevo__', label: '➕ Crear chofer nuevo' }]
        .concat(libres.map(function (c) { return { value: c.id, label: c.nombre + ' (' + c.desempeno + ')' }; }));
      var tipoOpts = K.TIPOS.map(function (t) { return { value: t.k, label: t.label + ' · cap ' + t.cap }; });
      var nuevo = alta.choferSel === '__nuevo__';
      var footer = h('div', { style: { display: 'flex', gap: 8, justifyContent: 'flex-end' } },
        h(ui.Button, { variant: 'ghost', onClick: function () { setAlta(null); } }, 'Cancelar'),
        h(ui.Button, { variant: 'primary', disabled: !(alta.patente || '').trim(), onClick: crearVehiculoYAsignar }, 'Crear y asignar'));
      return h(ui.Modal, { open: true, title: 'Agregar vehículo a ' + K.labelZona(alta.zona), onClose: function () { setAlta(null); }, footer: footer },
        h('div', { style: { display: 'flex', flexDirection: 'column', gap: 12 } },
          h(ui.Field, { label: 'Patente' }, h(ui.Input, { value: alta.patente, placeholder: 'AB 123 CD', onChange: function (v) { setA({ patente: v }); } })),
          h(ui.Field, { label: 'Tipo / capacidad (volumetría)' }, h(ui.Select, { value: alta.tipoUnidad, options: tipoOpts, onChange: function (v) { setA({ tipoUnidad: v }); } })),
          h(ui.Field, { label: 'Chofer' }, h(ui.Select, { value: alta.choferSel, options: choferOpts, onChange: function (v) { setA({ choferSel: v }); } })),
          nuevo ? h('div', { style: { display: 'flex', gap: 12, flexWrap: 'wrap' } },
            h(ui.Field, { label: 'Nombre del chofer', className: 'row-grow' }, h(ui.Input, { value: alta.nombre, placeholder: 'Apellido', onChange: function (v) { setA({ nombre: v }); } })),
            h(ui.Field, { label: 'Desempeño (0-100)' }, h(ui.Input, { type: 'number', value: alta.desempeno, onChange: function (v) { setA({ desempeno: v }); } }))) : null,
          h('p', { className: 'muted', style: { fontSize: 12, margin: 0 } }, 'Se crea la unidad, se suma a la flota del día y se reparte la carga de la zona automáticamente.')));
    }
  }

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