'use strict';
(function() {
  const MODEL_LABELS = {
    'claude-haiku-4-5-20251001': 'Haiku 4.5',
    'claude-sonnet-4-6': 'Sonnet 4.6',
    'claude-opus-4-6': 'Opus 4.6',
    'claude-3-5-sonnet-20241022': 'Sonnet 3.5',
    'gpt-4o-mini': 'GPT-4o Mini',
    'gpt-4o': 'GPT-4o',
    'o4-mini': 'o4-mini',
    'gemini-2.5-flash': 'Gemini Flash',
    'gemini-2.5-pro': 'Gemini Pro',
  };

  var ctmPort = parseInt(location.port) || 3456;
  var walleBase = 'http://localhost:' + (ctmPort + 1);
  var baseResolved = false;
  var resolvePromise = null;

  function resolveWalleBase() {
    if (baseResolved) return Promise.resolve(walleBase);
    if (resolvePromise) return resolvePromise;
    resolvePromise = fetch(walleBase + '/api/wall-e/health', { signal: AbortSignal.timeout(2000) })
      .then(function() { baseResolved = true; return walleBase; })
      .catch(function() {
        walleBase = '';
        baseResolved = true;
        return walleBase;
      });
    return resolvePromise;
  }

  resolveWalleBase();

  function withAuthHeaders(opts) {
    var next = Object.assign({}, opts || {});
    var headers = Object.assign({}, next.headers || {});
    var token = window._ctmState?.token || '';
    if (token) headers.Authorization = 'Bearer ' + token;
    next.headers = headers;
    return next;
  }

  function api(path, opts) {
    return resolveWalleBase().then(function() {
      var url = walleBase + '/api/wall-e' + path;
      return fetch(url, withAuthHeaders(opts)).then(function(r) {
        if (!r.ok) return r.json().then(function(d) { throw Object.assign(new Error(d.error || r.statusText), d); });
        return r.json();
      });
    });
  }

  function apiPost(path, body) {
    return resolveWalleBase().then(function() {
      return fetch(walleBase + '/api/wall-e' + path, withAuthHeaders({
        method: 'POST',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(body)
      })).then(function(r) { return r.json(); });
    });
  }

  function apiPut(path, body) {
    return resolveWalleBase().then(function() {
      return fetch(walleBase + '/api/wall-e' + path, withAuthHeaders({
        method: 'PUT',
        headers: {'Content-Type': 'application/json'},
        body: JSON.stringify(body)
      })).then(function(r) { return r.json(); });
    });
  }

  function apiDelete(path) {
    return resolveWalleBase().then(function() {
      return fetch(walleBase + '/api/wall-e' + path, withAuthHeaders({
        method: 'DELETE'
      })).then(function(r) { return r.json(); });
    });
  }

  function esc(s) {
    if (!s) return '';
    return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
  }

  function escImgSrc(s) {
    if (!s) return '';
    if (s.indexOf('data:image/') === 0 || s.indexOf('/api/') === 0) {
      return s.replace(/&/g, '&amp;').replace(/"/g, '&quot;');
    }
    return '';
  }

  function renderMarkdown(s) {
    if (!s) return '';
    var str = esc(s);
    var codeBlocks = [];
    str = str.replace(/```(\w*)\n?([\s\S]*?)```/g, function(_, lang, code) {
      var idx = codeBlocks.length;
      codeBlocks.push('<pre class="we-code-block"><code>' + code.replace(/\n$/, '') + '</code></pre>');
      return '\x00CB' + idx + '\x00';
    });
    var inlineCodes = [];
    str = str.replace(/`([^`]+)`/g, function(_, code) {
      var idx = inlineCodes.length;
      inlineCodes.push('<code class="we-inline-code">' + code + '</code>');
      return '\x00IC' + idx + '\x00';
    });
    str = str.replace(/^#### (.+)$/gm, '<h4 class="we-h4">$1</h4>');
    str = str.replace(/^### (.+)$/gm, '<h4 class="we-h4">$1</h4>');
    str = str.replace(/^## (.+)$/gm, '<h3 class="we-h3">$1</h3>');
    str = str.replace(/^# (.+)$/gm, '<h2 class="we-h2">$1</h2>');
    str = str.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>');
    str = str.replace(/(?<!\*)\*([^*]+?)\*(?!\*)/g, '<em>$1</em>');
    str = str.replace(/^&gt; (.+)$/gm, '<blockquote class="we-quote">$1</blockquote>');
    str = str.replace(/<\/blockquote>\n<blockquote class="we-quote">/g, '<br>');
    str = str.replace(/^---$/gm, '<hr class="we-hr">');
    str = str.replace(/^(\d+)\. (.+)$/gm, '<li class="we-ol-li" value="$1">$2</li>');
    str = str.replace(/((?:<li class="we-ol-li"[^>]*>[\s\S]*?<\/li>\n?)+)/g, function(match) {
      return '<ol class="we-ol">' + match + '</ol>';
    });
    str = str.replace(/^- (.+)$/gm, '<li class="we-li">$1</li>');
    str = str.replace(/((?:<li class="we-li">[\s\S]*?<\/li>\n?)+)/g, function(match) {
      return '<ul class="we-ul">' + match + '</ul>';
    });
    str = str.replace(/<\/ul>\n<ul class="we-ul">/g, '\n');
    str = str.replace(/<\/ol>\n<ol class="we-ol">/g, '\n');
    str = str.replace(/(<ul class="we-ul">)([\s\S]*?)(<\/ul>)/g, function(_, open, inner, close) {
      return open + inner.replace(/\n/g, '') + close;
    });
    str = str.replace(/(<ol class="we-ol">)([\s\S]*?)(<\/ol>)/g, function(_, open, inner, close) {
      return open + inner.replace(/\n/g, '') + close;
    });
    str = str.replace(/\n\n/g, '</p><p class="we-p">');
    str = str.replace(/\n/g, '<br>');
    str = '<p class="we-p">' + str + '</p>';
    str = str.replace(/<p class="we-p"><\/p>/g, '');
    str = str.replace(/<p class="we-p">(<h[234][^>]*>)/g, '$1');
    str = str.replace(/(<\/h[234]>)<\/p>/g, '$1');
    str = str.replace(/<p class="we-p">(<pre[^>]*>)/g, '$1');
    str = str.replace(/(<\/pre>)<\/p>/g, '$1');
    str = str.replace(/<p class="we-p">(<blockquote[^>]*>)/g, '$1');
    str = str.replace(/(<\/blockquote>)<\/p>/g, '$1');
    str = str.replace(/<p class="we-p">(<[uo]l[^>]*>)/g, '$1');
    str = str.replace(/(<\/[uo]l>)<\/p>/g, '$1');
    str = str.replace(/<p class="we-p">(<hr[^>]*>)/g, '$1');
    str = str.replace(/(<hr[^>]*>)<\/p>/g, '$1');
    str = str.replace(/<br><\/p>/g, '</p>');
    str = str.replace(/<p class="we-p"><br>/g, '<p class="we-p">');
    str = str.replace(/<br>(<h[234][^>]*>)/g, '$1');
    str = str.replace(/(<\/h[234]>)<br>/g, '$1');
    str = str.replace(/<br>(<[uo]l[^>]*>)/g, '$1');
    str = str.replace(/(<\/[uo]l>)<br>/g, '$1');
    str = str.replace(/<br>(<blockquote)/g, '$1');
    str = str.replace(/(<\/blockquote>)<br>/g, '$1');
    str = str.replace(/<br>(<hr)/g, '$1');
    str = str.replace(/(<hr[^>]*>)<br>/g, '$1');
    str = str.replace(/<br>(<pre)/g, '$1');
    str = str.replace(/(<\/pre>)<br>/g, '$1');
    str = str.replace(/\x00CB(\d+)\x00/g, function(_, idx) { return codeBlocks[parseInt(idx)]; });
    str = str.replace(/\x00IC(\d+)\x00/g, function(_, idx) { return inlineCodes[parseInt(idx)]; });
    return str;
  }

  window.WalleCore = {
    MODEL_LABELS,
    api,
    apiDelete,
    apiPost,
    apiPut,
    esc,
    escImgSrc,
    renderMarkdown,
    resolveWalleBase,
  };
})();
