import { SUGGEST_LIMIT, SUGGEST_MIN_QUERY_LEN } from '../config/constants.js';
import { api } from '../core/api.js';
import { historyState, state, suggestState } from '../state/app-state.js';
import { getSuggestionFieldNameFromInput, positionSuggestionsForInput } from '../ui/events.js';

export function primeOrigInputs(container) {
  if (!container) return;
  container.querySelectorAll(".field-table__input[data-col$='_orig']").forEach((input) => {
    historyState.pendingEdits.delete(input);
  });
}


export function clearSuggestTimer() {
  if (suggestState.timer) {
    clearTimeout(suggestState.timer);
    suggestState.timer = null;
  }
}


export function abortSuggestRequest() {
  if (suggestState.inFlightController) {
    suggestState.inFlightController.abort();
    suggestState.inFlightController = null;
  }
}


export function ensureSuggestRoot() {
  if (suggestState.root) return suggestState.root;
  const root = document.createElement("div");
  root.className = "field-suggest";
  root.hidden = true;
  root.setAttribute("role", "listbox");
  root.setAttribute("aria-label", "Suggestions");
  root.addEventListener(
    "mousedown",
    (e) => {
      const row = e.target.closest(".field-suggest__item");
      if (!row || !root.contains(row)) return;
      e.preventDefault();
      e.stopPropagation();
      pickSuggestionByIndex(parseInt(row.dataset.suggestIndex || "", 10));
    },
    true
  );
  root.addEventListener("click", (e) => {
    const row = e.target.closest(".field-suggest__item");
    if (!row || !root.contains(row)) return;
    e.preventDefault();
    e.stopPropagation();
    pickSuggestionByIndex(parseInt(row.dataset.suggestIndex || "", 10));
  });
  root.addEventListener("mouseover", (e) => {
    const row = e.target.closest(".field-suggest__item");
    if (!row || !root.contains(row)) return;
    const index = parseInt(row.dataset.suggestIndex || "", 10);
    if (!Number.isFinite(index) || index === suggestState.highlightedIndex) return;
    suggestState.highlightedIndex = index;
    syncSuggestionHighlight();
  });
  document.body.appendChild(root);
  suggestState.root = root;
  return root;
}


function pickSuggestionByIndex(index) {
  if (!Number.isFinite(index) || index < 0 || index >= suggestState.items.length) return;
  applySuggestion(suggestState.items[index]);
}


function syncSuggestionHighlight() {
  const root = suggestState.root;
  if (!root) return;
  root.querySelectorAll(".field-suggest__item").forEach((row) => {
    const index = parseInt(row.dataset.suggestIndex || "", 10);
    const active = index === suggestState.highlightedIndex;
    row.classList.toggle("is-active", active);
    row.setAttribute("aria-selected", active ? "true" : "false");
  });
}


export function hideSuggestions() {
  clearSuggestTimer();
  abortSuggestRequest();
  suggestState.items = [];
  suggestState.highlightedIndex = -1;
  suggestState.activeInput = null;
  if (suggestState.root) {
    suggestState.root.hidden = true;
    suggestState.root.innerHTML = "";
  }
}


export function renderSuggestions() {
  const root = ensureSuggestRoot();
  root.innerHTML = "";
  if (!suggestState.items.length || !suggestState.activeInput) {
    root.hidden = true;
    return;
  }
  suggestState.items.forEach((item, index) => {
    const row = document.createElement("button");
    row.type = "button";
    row.className = "field-suggest__item";
    row.dataset.suggestIndex = String(index);
    if (index === suggestState.highlightedIndex) {
      row.classList.add("is-active");
    }
    row.textContent = item;
    row.setAttribute("role", "option");
    row.setAttribute("aria-selected", index === suggestState.highlightedIndex ? "true" : "false");
    root.appendChild(row);
  });
  positionSuggestionsForInput(suggestState.activeInput);
  root.hidden = false;
}


export function syncSuggestionHighlightFromState() {
  syncSuggestionHighlight();
}


export function applySuggestion(value) {
  const input = suggestState.activeInput;
  if (!input || input.readOnly) {
    hideSuggestions();
    return;
  }
  input.value = value;
  input.dispatchEvent(new Event("input", { bubbles: true }));
  hideSuggestions();
}


export function handleSuggestionKeydown(e) {
  const target = e.target;
  const activeInput = suggestState.activeInput;
  const visible = !!(suggestState.root && !suggestState.root.hidden && suggestState.items.length);
  if (!visible || !activeInput || target !== activeInput) return false;
  const hasModifier = e.ctrlKey || e.altKey || e.metaKey;
  if (hasModifier) return false;
  if (e.key === "ArrowDown") {
    e.preventDefault();
    e.stopImmediatePropagation();
    moveSuggestionHighlight(1);
    return true;
  }
  if (e.key === "ArrowUp") {
    e.preventDefault();
    e.stopImmediatePropagation();
    moveSuggestionHighlight(-1);
    return true;
  }
  if (e.key === "Tab") {
    if (suggestState.items.length > 0) {
      e.preventDefault();
      e.stopImmediatePropagation();
      applySuggestion(suggestState.items[0]);
      return true;
    }
    return false;
  }
  if (e.key === "Enter") {
    if (suggestState.highlightedIndex >= 0 && suggestState.highlightedIndex < suggestState.items.length) {
      e.preventDefault();
      e.stopImmediatePropagation();
      applySuggestion(suggestState.items[suggestState.highlightedIndex]);
      return true;
    }
    return false;
  }
  if (e.key === "Escape") {
    e.preventDefault();
    e.stopImmediatePropagation();
    hideSuggestions();
    return true;
  }
  return false;
}


export async function fetchSuggestionsForInput(input) {
  if (!input || input.readOnly) {
    hideSuggestions();
    return;
  }
  if (document.activeElement !== input) {
    hideSuggestions();
    return;
  }

  const fieldName = getSuggestionFieldNameFromInput(input);
  const query = String(input.value || "").trim();
  if (!fieldName || query.length < SUGGEST_MIN_QUERY_LEN) {
    hideSuggestions();
    return;
  }

  abortSuggestRequest();
  const controller = new AbortController();
  suggestState.inFlightController = controller;
  suggestState.activeInput = input;

  try {
    const params = new URLSearchParams({
      field_name: fieldName,
      q: query,
      limit: String(SUGGEST_LIMIT),
      ranking_mode: state.suggestRankingMode || "hybrid",
    });
    if (state.batch) {
      params.set("batch", String(state.batch));
    }
    const data = await api(
      `/api/suggest?${params.toString()}`,
      { signal: controller.signal }
    );
    if (controller.signal.aborted) return;
    if (document.activeElement !== input) {
      hideSuggestions();
      return;
    }
    const items = Array.isArray(data && data.suggestions) ? data.suggestions : [];
    if (!items.length) {
      hideSuggestions();
      return;
    }
    suggestState.items = items;
    suggestState.highlightedIndex = 0;
    suggestState.activeInput = input;
    renderSuggestions();
  } catch (e) {
    if (e && e.name === "AbortError") return;
    hideSuggestions();
  } finally {
    if (suggestState.inFlightController === controller) {
      suggestState.inFlightController = null;
    }
  }
}
