(function (global) {
  global.ARQ = global.ARQ || {};

  var ARQ_FEEDBACK_ICONS = {
    success: 'fas fa-check-circle',
    error: 'fas fa-times-circle',
    warning: 'fas fa-exclamation-triangle',
    info: 'fas fa-info-circle',
    question: 'fas fa-question-circle',
    danger: 'fas fa-trash-alt',
    trash: 'fas fa-trash-alt'
  };
  var ARQ_FEEDBACK_TITLES = {
    success: 'Listo',
    error: 'Error',
    warning: 'Atención',
    info: 'Aviso',
    question: 'Confirmar',
    danger: 'Eliminar',
    trash: 'Mover a papelera'
  };
  var ARQ_FEEDBACK_EMOJIS = {
    success: '✅',
    error: '⛔',
    warning: '⚠️',
    info: 'ℹ️',
    question: '❓',
    danger: '🗑️',
    trash: '🗑️'
  };

  function arqDetectFeedbackType(message, mode) {
    if (mode === 'prompt') return 'question';
    var s = String(message == null ? '' : message).toLowerCase();
    var isQuestion = mode === 'confirm' || /[¿?]/.test(s);
    if (isQuestion) {
      if (/(mover.*papelera|enviar.*papelera|a la papelera|to (the )?(recycle|trash)|move to (trash|recycle)|send to (trash|recycle))/.test(s)) return 'trash';
      if (/(permanent|definitiv|sin recuperaci|no podr[áa]n? (ser )?recuperar|cannot be recovered|cannot be undone|vaciar|empty (the )?(trash|recycle)|formatear|format reinstall|destruir|borrar de forma|wipe)/.test(s)) return 'danger';
      if (/(eliminar|borrar|quitar|remover|descartar|reset|restablecer|delete|remove|discard|reset)/.test(s)) return 'danger';
      if (/(papelera|trash|recycle bin)/.test(s)) return 'trash';
      return 'question';
    }
    if (/(error|fall(o|ó|a|aron)|no se pudo|no se puede|incorrect|inv[áa]lid|denegad|rechazad|prohibid|bloquead|caduca|expirad|expir[oó]|failed|cannot|can'?t|denied|forbidden|invalid)/.test(s)) return 'error';
    if (/(advertencia|atenci[oó]n|cuidado|warning|sin guardar|demasiad|requer|obligator|necesit|debes|debe iniciar|unsaved|required|attention)/.test(s)) return 'warning';
    if (/(guardad|creado|enviad|copiad|[éeE]xito|exitoso|completad|registrad|actualizad|configurad|listo|hecho|aplicad|generad|saved|created|sent|copied|success|completed|updated|configured|done|ready)/.test(s)) return 'success';
    return 'info';
  }

  function arqFeedbackIconClass(type) {
    return ARQ_FEEDBACK_ICONS[type] || ARQ_FEEDBACK_ICONS.info;
  }
  function arqFeedbackTitle(type) {
    return ARQ_FEEDBACK_TITLES[type] || ARQ_FEEDBACK_TITLES.info;
  }
  function arqFeedbackEmoji(type) {
    return ARQ_FEEDBACK_EMOJIS[type] || '';
  }

  ARQ.feedback = {
    detectType: arqDetectFeedbackType,
    iconClass: arqFeedbackIconClass,
    title: arqFeedbackTitle,
    emoji: arqFeedbackEmoji
  };

  function toast(msg, type) {
    var text = String(msg == null ? '' : msg);
    var resolvedType = type || arqDetectFeedbackType(text, 'alert');
    var $t = $('<div class="arq-toast"/>').attr('data-type', resolvedType);
    $t.append($('<i aria-hidden="true"/>').addClass(arqFeedbackIconClass(resolvedType) + ' arq-toast-icon'));
    $t.append($('<span class="arq-toast-text"/>').text(text));
    $('body').append($t);
    setTimeout(function () { $t.fadeOut(400, function () { $t.remove(); }); }, 2800);
  }

  function loadPrefs() {
    var defaults = {
      maxUndo: 50,
      autosaveSec: 30,
      stylusOnly: false,
      rotateGesture: true,
      pngQuality: 0.92,
    };
    var p = ARQ.storage.get(ARQ.STORAGE_KEYS.UI_PREFS);
    if (!p) return defaults;
    var merged = Object.assign({}, defaults, p);
    if (!merged.stylusPrefsV2) {
      merged.stylusOnly = false;
      merged.stylusPrefsV2 = true;
      ARQ.storage.set(ARQ.STORAGE_KEYS.UI_PREFS, merged);
    }
    return merged;
  }

  function savePrefs(p) {
    ARQ.storage.set(ARQ.STORAGE_KEYS.UI_PREFS, p);
  }

  function refreshDashboard() {
    var $list = $('#dash-project-list');
    var $empty = $('#dash-empty');
    $('#dash-sync-status').text('Cargando…');
    ARQ.projects.list().then(function (r) {
      $('#dash-sync-status').text('Listo');
      $list.empty();
      if (!r.success || !r.projects || !r.projects.length) {
        $empty.removeAttr('hidden');
        return;
      }
      $empty.attr('hidden', true);
      var q = ($('#dash-search').val() || '').toLowerCase();
      r.projects.forEach(function (pr) {
        if (q && (pr.nombre || '').toLowerCase().indexOf(q) < 0) return;
        var $card = $('<div class="arq-project-card"/>');
        var $thumb = $('<div class="arq-project-card-thumb"/>');
        if (pr.miniatura_principal) {
          $thumb.append($('<img alt=""/>').attr('src', '../' + pr.miniatura_principal));
        } else {
          $thumb.text('Sin vista previa');
        }
        var $body = $('<div class="arq-project-card-body"/>');
        var $titleRow = $('<div class="arq-project-card-title-row"/>');
        $titleRow.append($('<h3 class="arq-ellipsis"/>').text(pr.nombre || pr.id));
        var hasGeo = !!(pr.ubicacion_textual || (pr.coordenadas && pr.coordenadas.lat != null && pr.coordenadas.lon != null));
        $body.append($titleRow);

        function projectActionBtn(extraClass, iconClass, label, handler) {
          var $b = $('<button type="button" class="arq-btn arq-btn--with-icon arq-btn--square ' + (extraClass || '') + '"/>');
          $b.append($('<span class="arq-btn-icon" aria-hidden="true"/>').html('<i class="fas ' + iconClass + '"></i>'));
          $b.append($('<span class="arq-btn-text"/>').text(label));
          $b.on('click', handler);
          return $b;
        }

        function wireProjectActions($container, pr) {
          $container.append(projectActionBtn('arq-btn--primary', 'fa-folder-open', 'Abrir', function (e) {
            e.stopPropagation();
            openProjectById(pr.id);
          }));
          $container.append(projectActionBtn('', 'fa-copy', 'Duplicar', function (e) {
            e.stopPropagation();
            ARQ.projects.duplicate(pr.id).then(function (res) {
              if (res.success) refreshDashboard();
              else toast(res.error || 'Error');
            });
          }));
          $container.append(projectActionBtn('', 'fa-edit', 'Renombrar', function (e) {
            e.stopPropagation();
            ARQ.dialog.prompt('Nuevo nombre', pr.nombre).then(function (n) {
              if (n) {
                ARQ.projects.rename(pr.id, n.trim()).then(function (res) {
                  if (res.success) refreshDashboard();
                });
              }
            });
          }));
          $container.append(projectActionBtn('', 'fa-trash-alt', 'Eliminar', function (e) {
            e.stopPropagation();
            ARQ.dialog.confirm('¿Eliminar proyecto?').then(function (ok) {
              if (!ok) return;
              ARQ.projects.remove(pr.id).then(function (res) {
                if (res.success) refreshDashboard();
              });
            });
          }));
          $container.append(projectActionBtn('', 'fa-map-marker-alt', 'Ubicación', function (e) {
            e.stopPropagation();
            openProjectLocationModal(pr);
          }));
        }

        var $geoDetails = $('<div class="arq-project-geo-details" hidden/>');
        if (hasGeo) {
          if (pr.ubicacion_textual) {
            $geoDetails.append($('<div class="arq-project-geo-line"/>').text(pr.ubicacion_textual));
          }
          if (pr.coordenadas && pr.coordenadas.lat != null && pr.coordenadas.lon != null) {
            var lat = pr.coordenadas.lat;
            var lon = pr.coordenadas.lon;
            var acc = pr.coordenadas.accuracy != null ? (' ±' + Math.round(pr.coordenadas.accuracy) + 'm') : '';
            $geoDetails.append($('<div class="arq-project-geo-line arq-muted"/>').text(lat.toFixed(6) + ', ' + lon.toFixed(6) + acc));
            var mapHref = 'https://www.openstreetmap.org/?mlat=' + encodeURIComponent(lat) + '&mlon=' + encodeURIComponent(lon) + '#map=16/' + encodeURIComponent(lat) + '/' + encodeURIComponent(lon);
            $geoDetails.append(
              $('<a class="arq-project-geo-link" target="_blank" rel="noopener noreferrer"/>').attr('href', mapHref).text('Ver en mapa')
            );
            var d = 0.01;
            var left = (lon - d), right = (lon + d), top = (lat + d), bottom = (lat - d);
            var src = 'https://www.openstreetmap.org/export/embed.html?bbox=' +
              [left, bottom, right, top].join('%2C') + '&layer=mapnik&marker=' + lat + '%2C' + lon;
            var $mapCircle = $('<div class="arq-project-geo-map-circle"/>');
            $mapCircle.append($('<iframe title="Mapa" loading="lazy" referrerpolicy="no-referrer-when-downgrade"/>').attr('src', src));
            var gHref = 'https://www.google.com/maps?q=' + encodeURIComponent(lat + ',' + lon);
            $mapCircle.append(
              $('<a class="arq-project-geo-map-click" target="_blank" rel="noopener noreferrer" aria-label="Abrir en Google Maps"/>').attr('href', gHref)
            );
            $geoDetails.append($('<div style="display:flex;justify-content:center"/>').append($mapCircle));
          }
        } else {
          $geoDetails.append($('<div class="arq-muted"/>').text('Sin ubicación guardada'));
        }
        var $act = $('<div class="arq-project-card-actions" aria-label="Acciones del proyecto"/>');
        wireProjectActions($act, pr);

        var $menuBtn = $('<button type="button" class="arq-project-card-menu-btn" aria-label="Más acciones" aria-haspopup="true" aria-expanded="false"/>')
          .append($('<span class="arq-btn-icon" aria-hidden="true"/>').html('<i class="fas fa-ellipsis-v"></i>'));
        var $dropdown = $('<div class="arq-project-card-dropdown" role="menu" hidden/>');
        wireProjectActions($dropdown, pr);

        $menuBtn.on('click', function (e) {
          e.stopPropagation();
          var wasOpen = !$dropdown.prop('hidden');
          $('#dash-project-list .arq-project-card-dropdown').attr('hidden', true);
          $('#dash-project-list .arq-project-card-menu-btn').attr('aria-expanded', 'false');
          if (!wasOpen) {
            $dropdown.removeAttr('hidden');
            $menuBtn.attr('aria-expanded', 'true');
          }
        });
        $dropdown.on('click', function (e) { e.stopPropagation(); });

        $thumb.append($menuBtn, $dropdown);
        $body.append($act);
        $card.append($thumb, $body);
        $card.on('click', function (e) {
          if ($(e.target).closest('.arq-project-card-menu-btn, .arq-project-card-dropdown').length) return;
          openProjectById(pr.id);
        });
        $list.append($card);
      });
    }).catch(function () {
      $('#dash-sync-status').text('Sin conexión');
      toast('No se pudo listar proyectos');
    });
  }

  function openProjectLocationModal(pr) {
    var hasGeo = !!(pr && (pr.ubicacion_textual || (pr.coordenadas && pr.coordenadas.lat != null && pr.coordenadas.lon != null)));
    var $body = $('<div/>');
    if (!hasGeo) {
      $body.append($('<p class="arq-muted"/>').text('Este proyecto no tiene ubicación guardada.'));
      var dlg0 = ARQ.dialog.open({
        title: 'Ubicación',
        body: $body,
        buttons: [{ label: 'Cerrar', primary: true, onClick: function () { dlg0.close(); } }],
        onCancel: function () { dlg0.close(); },
      });
      return;
    }

    if (pr.ubicacion_textual) {
      $body.append($('<div class="arq-project-geo-line"/>').text(pr.ubicacion_textual));
    }
    var gHref = '';
    if (pr.coordenadas && pr.coordenadas.lat != null && pr.coordenadas.lon != null) {
      var lat = pr.coordenadas.lat;
      var lon = pr.coordenadas.lon;
      var acc = pr.coordenadas.accuracy != null ? (' ±' + Math.round(pr.coordenadas.accuracy) + 'm') : '';
      $body.append($('<div class="arq-project-geo-line arq-muted"/>').text(lat.toFixed(6) + ', ' + lon.toFixed(6) + acc));
      gHref = 'https://www.google.com/maps?q=' + encodeURIComponent(lat + ',' + lon);

      var d = 0.01;
      var left = (lon - d), right = (lon + d), top = (lat + d), bottom = (lat - d);
      var src = 'https://www.openstreetmap.org/export/embed.html?bbox=' +
        [left, bottom, right, top].join('%2C') + '&layer=mapnik&marker=' + lat + '%2C' + lon;
      var $mapCircle = $('<div class="arq-project-geo-map-circle arq-project-geo-map-circle--lg"/>');
      $mapCircle.append($('<iframe title="Mapa" loading="lazy" referrerpolicy="no-referrer-when-downgrade"/>').attr('src', src));
      $body.append($('<div style="display:flex;justify-content:center"/>').append($mapCircle));
    }

    var dlg = ARQ.dialog.open({
      title: 'Ubicación',
      body: $body,
      buttons: [
        { label: 'Cerrar', onClick: function () { dlg.close(); } },
        { label: 'Abrir en Google Maps', primary: true, onClick: function () {
          if (gHref) global.open(gHref, '_blank');
        } },
      ],
      onCancel: function () { dlg.close(); },
    });
  }

  function openProjectById(id) {
    var run = function (opCtx) {
      var oid = opCtx && opCtx.id;
      var timer = null;
      var fake = 0;
      if (oid && ARQ.ops && ARQ.ops.step) {
        timer = global.setInterval(function () {
          if (fake < 82) {
            fake += 3 + Math.random() * 6;
            if (fake > 82) fake = 82;
            ARQ.ops.step(oid, 'Descargando proyecto…', 'net', Math.floor(fake));
          }
        }, 160);
      }
      return ARQ.projects.load(id).then(function (r) {
        if (timer) global.clearInterval(timer);
        timer = null;
        if (r.success && r.project) {
          if (oid && ARQ.ops && ARQ.ops.step) {
            ARQ.ops.step(oid, 'Montando proyecto en el editor…', 'mount', 92);
          }
          ARQ.editor.openProject(r.project);
          ARQ.router.go('editor');
          if (oid && ARQ.ops && ARQ.ops.step) {
            ARQ.ops.step(oid, 'Listo', 'done', 100);
          }
          return new Promise(function (resolve) {
            global.setTimeout(function () {
              resolve(r);
            }, 100);
          });
        }
        return Promise.reject(new Error(r.error || 'No se pudo abrir'));
      }).catch(function (err) {
        if (timer) global.clearInterval(timer);
        throw err;
      });
    };
    if (ARQ.ops && ARQ.ops.run) {
      ARQ.ops.run(run, {
        id: 'openProject',
        label: 'Descargando proyecto…',
        blocking: 'critical',
        progress: 0,
      }).catch(function () {});
    } else {
      run({}).catch(function (e) { toast(e.message || 'No se pudo abrir'); });
    }
  }

  function captureThumbnailUpload(project) {
    return new Promise(function (resolve) {
      try {
        var canvas = document.getElementById('arq-main-canvas');
        if (!canvas) return resolve(null);
        var w = canvas.width || 1920;
        var h = canvas.height || 1080;
        if (!w || !h) return resolve(null);
        var maxW = 520;
        var scale = Math.min(1, maxW / w);
        var tw = Math.max(1, Math.round(w * scale));
        var th = Math.max(1, Math.round(h * scale));
        var off = document.createElement('canvas');
        off.width = tw;
        off.height = th;
        var octx = off.getContext('2d');
        if (!octx) return resolve(null);
        octx.drawImage(canvas, 0, 0, tw, th);
        off.toBlob(function (blob) {
          if (!blob) return resolve(null);
          var file = new File([blob], 'thumb_' + Date.now() + '.jpg', { type: 'image/jpeg' });
          ARQ.projects.uploadFile(project.id, 'thumbs', file).then(function (r) {
            if (r && r.success && r.path) resolve(r.path);
            else resolve(null);
          }).catch(function () { resolve(null); });
        }, 'image/jpeg', 0.82);
      } catch (e) {
        resolve(null);
      }
    });
  }

  function saveProjectNow(opts) {
    opts = opts || {};
    var p = ARQ.store.getProject();
    if (!p) return Promise.resolve();
    var doThumb = !!opts.withThumbnail;
    var label = opts.autosaveSilent ? 'Guardando…' : 'Guardando cambios…';
    var inner = function () {
      var chain = Promise.resolve(null);
      if (doThumb) {
        chain = captureThumbnailUpload(p).then(function (path) {
          if (path) p.miniatura_principal = path;
          return path;
        });
      }
      return chain.then(function () {
        return ARQ.projects.save(p).then(function (r) {
          $('#editor-autosave-pill').removeClass('is-saving');
          if (r.success) {
            ARQ.store.setDirty(false);
            $('#editor-autosave-pill').text('Guardado').removeClass('is-dirty');
            ARQ.bus.emit(ARQ.EVENTS.PROJECT_SAVED);
            return r;
          }
          $('#editor-autosave-pill').text('Error');
          return Promise.reject(new Error(r.error || 'Error al guardar'));
        });
      });
    };
    if (ARQ.ops && ARQ.ops.run) {
      return ARQ.ops.run(inner, { id: 'save', label: label, blocking: 'medium' }).catch(function () {
        $('#editor-autosave-pill').removeClass('is-saving');
      });
    }
    $('#editor-autosave-pill').text('Guardando…').addClass('is-saving');
    return inner().catch(function () {
      $('#editor-autosave-pill').removeClass('is-saving');
      toast('Error de red al guardar');
    });
  }

  ARQ.boot = function () {
    var prefs = loadPrefs();
    ARQ.bus.on(ARQ.EVENTS.TOAST, function (m) { toast(m); });
    ARQ.bus.on(ARQ.EVENTS.DIRTY, function (d) {
      $('#editor-autosave-pill').toggleClass('is-dirty', d).text(d ? 'Cambios sin guardar' : 'Guardado');
    });

    if (ARQ.opsFeedback && ARQ.opsFeedback.init) ARQ.opsFeedback.init();
    if (ARQ.aiGate && ARQ.aiGate.init) ARQ.aiGate.init();

    ARQ.editor.init();
    ARQ.aiChat.init();

    $('#btn-new-project').on('click', function () {
      ARQ.dialogProject.openNew(function (project) {
        refreshDashboard();
        ARQ.editor.openProject(project);
        ARQ.router.go('editor');
      });
    });
    $('#btn-dash-settings, #btn-editor-settings').on('click', function () {
      ARQ.router.go('settings');
      applySettingsForm();
    });
    $('#btn-dash-about').on('click', function () { ARQ.router.go('about'); });
    $('#btn-about-back').on('click', function () { ARQ.router.go('dashboard'); });
    $('#btn-settings-back').on('click', function () {
      if (ARQ.store.getProject()) ARQ.router.go('editor');
      else ARQ.router.go('dashboard');
    });

    $('#dash-search').on('input', ARQ.utils.debounce(refreshDashboard, 200));

    $(document).on('click', function (e) {
      if ($(e.target).closest('.arq-project-card-menu-btn, .arq-project-card-dropdown').length) return;
      $('#dash-project-list .arq-project-card-dropdown').attr('hidden', true);
      $('#dash-project-list .arq-project-card-menu-btn').attr('aria-expanded', 'false');
    });

    function goDashFromEditor() {
      saveProjectNow({ withThumbnail: true }).then(function () {
        ARQ.router.go('dashboard');
        refreshDashboard();
      }, function () {
        ARQ.router.go('dashboard');
        refreshDashboard();
      });
    }
    $('#btn-back-dashboard').on('click', function () {
      if (ARQ.store.isDirty()) {
        ARQ.dialog.confirm('Hay cambios sin guardar. ¿Salir?').then(function (ok) {
          if (!ok) return;
          goDashFromEditor();
        });
        return;
      }
      goDashFromEditor();
    });

    $('#btn-save-now').on('click', function () { saveProjectNow({ withThumbnail: true }); });

    $('#settings-max-undo').val(prefs.maxUndo);
    $('#settings-autosave').val(prefs.autosaveSec);
    $('#settings-stylus-only').prop('checked', prefs.stylusOnly === true);
    $('#settings-rotate-gesture').prop('checked', prefs.rotateGesture !== false);
    $('#settings-png-quality').val(prefs.pngQuality || 0.92);

    function applySettingsForm() {
      var pr = loadPrefs();
      $('#settings-max-undo').val(pr.maxUndo);
      $('#settings-autosave').val(pr.autosaveSec);
      $('#settings-stylus-only').prop('checked', pr.stylusOnly === true);
      $('#settings-rotate-gesture').prop('checked', pr.rotateGesture !== false);
      $('#settings-png-quality').val(pr.pngQuality || 0.92);
    }

    $('#btn-save-openai').on('click', function () {
      var k = ($('#settings-openai-key').val() || '').trim();
      ARQ.projects.saveOpenaiKey(k).then(function (r) {
        toast(r.success ? 'Clave guardada' : (r.error || 'Error'));
        $('#settings-openai-key').val('');
        ARQ.aiChat.refreshGate();
        if (ARQ.aiGate && ARQ.aiGate.refresh) ARQ.aiGate.refresh();
        if (ARQ.layers && ARQ.layers.renderPanel) ARQ.layers.renderPanel();
        if (ARQ.aiGlobal && ARQ.aiGlobal.syncUi) ARQ.aiGlobal.syncUi();
      });
    });
    $('#btn-clear-openai').on('click', function () {
      ARQ.projects.saveOpenaiKey('').then(function () {
        toast('Clave eliminada');
        ARQ.aiChat.refreshGate();
        if (ARQ.aiGate && ARQ.aiGate.refresh) ARQ.aiGate.refresh();
        if (ARQ.layers && ARQ.layers.renderPanel) ARQ.layers.renderPanel();
        if (ARQ.aiGlobal && ARQ.aiGlobal.syncUi) ARQ.aiGlobal.syncUi();
      });
    });

    function persistUiPrefs() {
      var prev = loadPrefs();
      savePrefs(Object.assign({}, prev, {
        maxUndo: parseInt($('#settings-max-undo').val(), 10) || 50,
        autosaveSec: parseInt($('#settings-autosave').val(), 10) || 30,
        stylusOnly: $('#settings-stylus-only').is(':checked'),
        rotateGesture: $('#settings-rotate-gesture').is(':checked'),
        pngQuality: parseFloat($('#settings-png-quality').val()) || 0.92,
      }));
    }

    $('#settings-max-undo, #settings-autosave, #settings-stylus-only, #settings-rotate-gesture, #settings-png-quality').on('change', persistUiPrefs);

    setInterval(function () {
      if (ARQ.store.getProject() && ARQ.store.isDirty()) {
        saveProjectNow({ withThumbnail: false, autosaveSilent: true });
      }
    }, Math.max(5000, (loadPrefs().autosaveSec || 30) * 1000));

    global.addEventListener('beforeunload', function (e) {
      if (ARQ.store.isDirty()) {
        e.preventDefault();
        e.returnValue = '';
      }
    });

    $('#about-version').text('Versión ' + ARQ.config.version);
    refreshDashboard();
  };

  $(function () { ARQ.boot(); });
})(typeof window !== 'undefined' ? window : this);
