/**
 * Slow Lane Client: Backend context encoding for autocomplete.
 *
 * Fires a BE request on word boundaries to encode document context.
 * Expects the typeahead-encodings API format:
 *   Request:  { text, session_id }
 *   Response: { semantic_vector: number[], lm_logits: Record<string, number> }
 */

import { abortExp, EXPERIENCE_NAME, failExp, startExp, succeedExp } from '../analytics/ufo';
import { isAutocompleteDebugEnabled } from './debug-mode';

// ─── Types ───────────────────────────────────────────────────────────────────

/** Request payload for typeahead-encodings endpoint. */

/** Response from typeahead-encodings endpoint. */

// ─── Constants ───────────────────────────────────────────────────────────────

// eslint-disable-next-line require-unicode-regexp
const WORD_BOUNDARY_CHARS = /[\s.,;:!?]/;
// eslint-disable-next-line require-unicode-regexp
const TRAILING_SLASH_REGEX = /\/$/;
const DEFAULT_DEBOUNCE_MS = 300;

/**
 * Check if text ends with a word boundary character (space or punctuation).
 */
export const isWordBoundary = text => {
  if (!text || text.length === 0) {
    return false;
  }
  const lastChar = text[text.length - 1];
  return WORD_BOUNDARY_CHARS.test(lastChar);
};

// ─── Slow Lane Client ────────────────────────────────────────────────────────

export const createSlowLaneClient = config => {
  const {
    baseUrl,
    sessionId: configSessionId,
    productKey = 'confluence',
    endpoint = '/gateway/api/v1/autocomplete/typeahead-encodings',
    debounceMs = DEFAULT_DEBOUNCE_MS,
    fetchFn = fetch,
    onUpdate
  } = config;
  const sessionId = configSessionId !== null && configSessionId !== void 0 ? configSessionId : crypto.randomUUID();
  const headers = {
    'Content-Type': 'application/json',
    'x-experience-id': 'confluence-smart-typeahead-encodings',
    'x-product': productKey
  };
  let debounceTimer = null;
  let lastRequestedText = '';
  let storedContextVector = null;
  let storedLmLogits = null;
  let requestSeq = 0;
  let inflightRequestId = null;
  const doUpdateContext = async (text, requestId) => {
    if (!text || text.trim().length === 0) {
      return;
    }
    const url = `${baseUrl.replace(TRAILING_SLASH_REGEX, '')}${endpoint}`;
    const payload = {
      text,
      session_id: sessionId
    };
    startExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
      textLength: text.length,
      isLocalLLM: false
    });
    if (isAutocompleteDebugEnabled()) {
      // eslint-disable-next-line no-console
      console.groupCollapsed(`%c[SlowLane] %c📤 Sending context | ${text.length} chars`, 'color: #9c27b0; font-weight: bold;', 'color: inherit;');
      text.split('\n').forEach((line, i, arr) => {
        // eslint-disable-next-line no-console
        console.log(`  ${i === arr.length - 1 ? '▶' : ' '} ${line}`);
      });
      // eslint-disable-next-line no-console
      console.groupEnd();
    }
    try {
      const res = await fetchFn(url, {
        method: 'POST',
        headers,
        body: JSON.stringify(payload)
      });
      if (!res.ok) {
        storedContextVector = null;
        storedLmLogits = null;
        failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
          status: res.status,
          errorType: 'http_error',
          isLocalLLM: false
        });
        if (isAutocompleteDebugEnabled()) {
          // eslint-disable-next-line no-console
          console.log(`%c[SlowLane] %c❌ Request failed (${res.status})`, 'color: #9c27b0; font-weight: bold;', 'color: #f44336;');
        }
        return;
      }
      const data = await res.json();
      if (data.semantic_vector && Array.isArray(data.semantic_vector)) {
        storedContextVector = new Float32Array(data.semantic_vector);
      } else {
        storedContextVector = null;
      }
      if (data.lm_logits && typeof data.lm_logits === 'object') {
        storedLmLogits = data.lm_logits;
      } else {
        storedLmLogits = null;
      }
      if (isAutocompleteDebugEnabled()) {
        // eslint-disable-next-line no-console
        console.groupCollapsed(`%c[SlowLane] %c📥 Response received`, 'color: #9c27b0; font-weight: bold;', 'color: inherit;');
        // eslint-disable-next-line no-console
        console.log(storedContextVector ? `✅ semantic_vector: ${storedContextVector.length} dims` : '❌ No semantic_vector');
        // eslint-disable-next-line no-console
        console.log(storedLmLogits ? `✅ lm_logits: ${Object.keys(storedLmLogits).length} tokens` : '❌ No lm_logits');
        // eslint-disable-next-line no-console
        console.groupEnd();
      }
      succeedExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
        textLength: text.length,
        hasVector: storedContextVector !== null,
        hasLmLogits: storedLmLogits !== null,
        isLocalLLM: false
      });
      onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate({
        textLength: text.length,
        hasVector: storedContextVector !== null,
        hasLmLogits: storedLmLogits !== null
      });
      // eslint-disable-next-line no-unused-vars
    } catch (e) {
      storedContextVector = null;
      storedLmLogits = null;
      failExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, requestId, {
        errorType: 'network',
        isLocalLLM: false
      });
      if (isAutocompleteDebugEnabled()) {
        // eslint-disable-next-line no-console
        console.log('%c[SlowLane] %c❌ Network error — context cleared', 'color: #9c27b0; font-weight: bold;', 'color: #f44336;');
      }
    } finally {
      if (inflightRequestId === requestId) {
        inflightRequestId = null;
      }
    }
  };
  const updateContextDebounced = text => {
    if (debounceTimer) {
      clearTimeout(debounceTimer);
    }
    lastRequestedText = text;
    debounceTimer = setTimeout(() => {
      debounceTimer = null;
      if (inflightRequestId !== null) {
        abortExp(EXPERIENCE_NAME.SLOW_LANE_FETCH, inflightRequestId, 'superseded', {
          isLocalLLM: false
        });
      }
      const requestId = String(++requestSeq);
      inflightRequestId = requestId;
      doUpdateContext(lastRequestedText, requestId);
    }, debounceMs);
  };
  return {
    updateContext: updateContextDebounced,
    getContextVector: () => storedContextVector,
    getLmLogits: () => storedLmLogits,
    setContextVector: vector => {
      storedContextVector = vector;
    },
    setLmLogits: logits => {
      storedLmLogits = logits;
    },
    isWordBoundary
  };
};
let defaultSlowLaneClient = null;
export const setDefaultSlowLaneClient = client => {
  defaultSlowLaneClient = client;
};
export const getStoredContextVector = () => {
  var _defaultSlowLaneClien, _defaultSlowLaneClien2;
  return (_defaultSlowLaneClien = (_defaultSlowLaneClien2 = defaultSlowLaneClient) === null || _defaultSlowLaneClien2 === void 0 ? void 0 : _defaultSlowLaneClien2.getContextVector()) !== null && _defaultSlowLaneClien !== void 0 ? _defaultSlowLaneClien : null;
};
export const getStoredLmLogits = () => {
  var _defaultSlowLaneClien3, _defaultSlowLaneClien4;
  return (_defaultSlowLaneClien3 = (_defaultSlowLaneClien4 = defaultSlowLaneClient) === null || _defaultSlowLaneClien4 === void 0 ? void 0 : _defaultSlowLaneClien4.getLmLogits()) !== null && _defaultSlowLaneClien3 !== void 0 ? _defaultSlowLaneClien3 : null;
};