// auxmenu.js — Standalone User Inquiry Menu & Navigator Component
// Owns the visible inquiry menu and menu-only filetree cache.

import { getHealth, retrieve, retrieveRaw } from './auxio.js';

let menuTreeFiles = [];
let menuTreePrefix = '';
let currentTreeTitle = 'Filetree';
let currentTreePick = null;
let currentTreeScope = '';

// ─────────────────────────────────────────────────────────────
// Core Overlay Panel Lifecycles
// ─────────────────────────────────────────────────────────────

export function showInquiryMenu() {
  removeInquiryPanel();

  const menu = document.createElement('div');
  menu.id = 'aux-ctx-menu';
  menu.className = 'Menu-Cx inquiry-deck-panel is-menu';
  menu.innerHTML = `
    <div class="ctx-title">FILE INQUIRY MENU</div>
    <button class="inquiry-clear-btn" type="button" id="menu-clear-btn">CLR</button>
    <button class="ctx-btn" data-req="check-connections" type="button">Check Connections</button>
    <button class="ctx-btn" data-req="project-outline" type="button">Get Project Details</button>
    <button class="ctx-btn" data-req="read-tree" type="button">Get Filetree</button>
    <button class="ctx-btn" data-req="read-file" type="button">Get File Details</button>
    <button class="ctx-btn" data-req="trace-menu" type="button">Trace Tools</button>
  `;

  menu.querySelector('#menu-clear-btn').onclick = removeInquiryPanel;

  menu.querySelectorAll('.ctx-btn').forEach(btn => {
    btn.onclick = event => {
      event.preventDefault();
      event.stopPropagation();
      handleMenuRequest(btn.dataset.req, menu);
    };
  });

  mountInquiryPanel(menu);
}

export function removeInquiryPanel() {
  const panel = document.getElementById('aux-ctx-menu');

  if (panel) {
    panel.remove();
  }

  document.querySelector('.Lowerframe-Cx')?.classList.remove('has-inquiry-menu');
}

function mountInquiryPanel(panel) {
  const lower = document.querySelector('.Lowerframe-Cx');
  if (!lower || !panel) return null;

  const existing = document.getElementById('aux-ctx-menu');

  if (existing && existing !== panel) {
    existing.replaceWith(panel);
  } else if (!existing) {
    const list = document.getElementById('linein-list');
    if (list) lower.insertBefore(panel, list);
    else lower.appendChild(panel);
  }

  lower.classList.add('has-inquiry-menu');
  return panel;
}

async function handleMenuRequest(request, menu) {
  const req = String(request || '').trim().toLowerCase();

  if (req === 'read-file') {
    const loaded = await ensureFiletreeLoaded();
    if (!loaded) return;

    renderTreeNavigator('Get File Details', file => {
      submitInquiryPacket({
        request: 'getfileinfo',
        FilePath: file
      });
    });
    return;
  }

  if (req === 'read-tree') {
    await loadFiletreeAndRender('Filetree');
    return;
  }

  if (req === 'project-outline') {
    submitInquiryPacket({ request: 'getprojectinfo' });
    return;
  }

  if (req === 'trace-menu') {
    renderTraceOptionsSubMenu(menu);
    return;
  }

  if (req === 'check-connections') {
    setInquiryPanelStatus('loading', 'Checking Verbatim connection...');

    getHealth().then(result => {
      setInquiryPanelStatus(
        result.ok ? 'ready' : 'failed',
        result.ok ? 'Verbatim connected' : `Verbatim offline: ${result.msg || 'Connection failed'}`
      );
    });

    return;
  }

  submitInquiryPacket({ request: req });
}
export async function renderTreeNavigator(title = 'Filetree', onPick = null, scope = '') {
  currentTreeTitle = title;
  currentTreePick = onPick;
  currentTreeScope = cleanPath(scope);

  const panel = document.getElementById('aux-ctx-menu') || document.createElement('div');
  panel.id = 'aux-ctx-menu';
  panel.className = 'Menu-Cx inquiry-deck-panel is-tree';

  const entries = getMenuFiletreeEntries(currentTreeScope);
  const listHtml = renderTreeList(entries);

  panel.innerHTML = `
    <div class="inquiry-tree-head">
      <span>${escHtml(title)}${entries.scope ? ` • ${escHtml(entries.scope)}` : ''}</span>
      <button class="inquiry-tree-root-btn" type="button">ROOT</button>
      <button class="inquiry-clear-btn" type="button" id="tree-clear-btn">CLR</button>
    </div>
    <input class="inquiry-tree-input" type="text" placeholder="filter or type filename..." />
    <div class="inquiry-tree-list">${listHtml}</div>
  `;

  bindTreeNavigator(panel, entries);
  mountInquiryPanel(panel);

  panel.querySelector('.inquiry-tree-input')?.focus();
}

async function ensureFiletreeLoaded() {
  if (menuTreeFiles.length) return true;
  await loadFiletree();
  return Boolean(menuTreeFiles.length);
}

async function loadFiletreeAndRender(title = 'Filetree', scope = '') {
  await loadFiletree(scope);
  renderTreeNavigator(title, null, scope);
}

async function loadFiletree(scope = '') {
  const cleanScope = cleanPath(scope);
  setInquiryPanelStatus('loading', cleanScope ? `Loading ${cleanScope}...` : 'Loading filetree...');

  try {
    // Silent fetch using retrieveRaw to keep directory metadata out of lineIn
    const reply = await retrieveRaw({
      request: 'getfiletree',
      path: cleanScope
    });

    updateMenuFileTree(reply);
    return reply;
  } catch (error) {
    setInquiryPanelStatus('failed', error?.message || 'Filetree request failed');
    return null;
  }
}

function bindTreeNavigator(panel, entries) {
  const input = panel.querySelector('.inquiry-tree-input');
  const list = panel.querySelector('.inquiry-tree-list');

  panel.querySelector('.inquiry-tree-root-btn').onclick = event => {
    event.preventDefault();
    event.stopPropagation();
    renderTreeNavigator(currentTreeTitle, currentTreePick, '');
  };

  panel.querySelector('#tree-clear-btn').onclick = removeInquiryPanel;

  list.onclick = event => {
    const folder = event.target.closest('.inquiry-tree-folder');
    if (folder) {
      event.preventDefault();
      renderTreeNavigator(currentTreeTitle, currentTreePick, decodeURIComponent(folder.dataset.path || ''));
      return;
    }

    const file = event.target.closest('.inquiry-tree-file');
    if (file) {
      event.preventDefault();
      chooseTreeFile(decodeURIComponent(file.dataset.file || ''));
    }
  };

  input.oninput = () => {
    const q = input.value.trim().toLowerCase();
    const directories = q
      ? entries.directories.filter(item => item.label.toLowerCase().includes(q))
      : entries.directories;
    const files = q
      ? entries.files.filter(item => item.label.toLowerCase().includes(q))
      : entries.files;

    list.innerHTML = renderTreeList({ directories, files });
  };
}

function chooseTreeFile(file) {
  if (!file) return;

  removeInquiryPanel();

  if (currentTreePick) {
    currentTreePick(file);
    return;
  }

  submitInquiryPacket({
    request: 'getfileinfo',
    FilePath: file
  });
}
function renderTreeList(entries = {}) {
  const directories = entries.directories || [];
  const files = entries.files || [];

  if (!directories.length && !files.length) {
    return menuTreeFiles.length
      ? '<div class="inquiry-tree-empty">No files in this folder.</div>'
      : '<div class="inquiry-tree-empty">No filetree loaded. Pull Filetree first.</div>';
  }

  return [
    ...directories.map(item => {
      return `<button class="inquiry-tree-folder" type="button" data-path="${escAttr(encodeURIComponent(item.path))}">▸ ${escHtml(item.label)}</button>`;
    }),
    ...files.slice(0, 180).map(item => {
      return `<button class="inquiry-tree-file" type="button" data-file="${escAttr(encodeURIComponent(item.path))}">${escHtml(item.label)}</button>`;
    })
  ].join('');
}

function updateMenuFileTree(data) {
  const files = extractFilePaths(data);

  menuTreeFiles = files;
  menuTreePrefix = inferProjectPrefix(files);

  return files;
}

function getMenuFiletreeEntries(scope = '') {
  const directories = new Map();
  const files = [];
  const cleanScope = stripProjectPrefix(scope);
  const scopePrefix = cleanScope ? `${cleanScope}/` : '';

  menuTreeFiles.forEach(path => {
    const label = stripProjectPrefix(path);

    if (cleanScope && label !== cleanScope && !label.startsWith(scopePrefix)) {
      return;
    }

    const relative = cleanScope && label.startsWith(scopePrefix)
      ? label.slice(scopePrefix.length)
      : label;

    if (!relative || relative === cleanScope) return;

    const parts = relative.split('/').filter(Boolean);

    if (parts.length > 1) {
      const folderLabel = parts[0];
      const folderPath = cleanPath(`${menuTreePrefix}${scopePrefix}${folderLabel}`);
      directories.set(folderLabel, folderPath);
      return;
    }

    files.push({ label: relative, path });
  });

  return {
    scope: cleanScope,
    directories: [...directories.entries()]
      .map(([label, path]) => ({ label, path }))
      .sort((a, b) => a.label.localeCompare(b.label)),
    files: files.sort((a, b) => a.label.localeCompare(b.label))
  };
}

function extractFilePaths(data) {
  const source = data?.data || data || {};
  const project = source?.project && typeof source.project === 'object' ? source.project : {};
  const tree = Array.isArray(source)
    ? source
    : source.prjMap ||
      source.fileTree ||
      source.tree ||
      source.files ||
      project.prjMap ||
      project.fileTree ||
      project.tree ||
      project.files ||
      [];

  const out = [];
  walkTree(tree, out);

  return [...new Set(out.map(cleanPath).filter(Boolean))].sort();
}

function walkTree(node, out) {
  if (Array.isArray(node)) {
    node.forEach(child => walkTree(child, out));
    return;
  }

  if (typeof node === 'string') {
    out.push(node);
    return;
  }

  if (!node || typeof node !== 'object') return;

  const type = String(node.type || node.kind || '').toLowerCase();
  const children = node.children || node.entries || node.items;

  if (children) {
    walkTree(children, out);
    return;
  }

  if (type === 'directory' || type === 'folder' || type === 'dir') return;

  const path = node.FilePath || node.filePath || node.path || node.name || node.label || '';
  if (path) out.push(path);
}

function inferProjectPrefix(files = []) {
  const clean = files.map(cleanPath).filter(Boolean);
  if (!clean.length) return '';

  const match = clean[0].match(/^(projects\/[^/]+)\//i);
  if (!match) return '';

  const prefix = `${match[1]}/`;
  return clean.every(file => file.startsWith(prefix)) ? prefix : '';
}

function stripProjectPrefix(path = '') {
  const clean = cleanPath(path);

  return menuTreePrefix && clean.startsWith(menuTreePrefix)
    ? clean.slice(menuTreePrefix.length)
    : clean;
}

function cleanPath(value = '') {
  return String(value || '')
    .replace(/\\/g, '/')
    .replace(/^\.\//, '')
    .replace(/^\/+/, '')
    .replace(/\/+$/, '')
    .trim();
}

// ─────────────────────────────────────────────────────────────
// Trace & Search Forms
// ─────────────────────────────────────────────────────────────

function renderTraceOptionsSubMenu(menu) {
  menu.className = 'Menu-Cx inquiry-deck-panel is-form';
  menu.innerHTML = `
    <div class="inquiry-tree-head">
      <span>Trace Tools</span>
      <button class="inquiry-clear-btn" type="button" id="trace-clear-btn">CLR</button>
    </div>
    <div class="inquiry-form-actions">
      <button class="ctx-btn" id="trace-find-btn" type="button">FIND</button>
      <button class="ctx-btn" id="trace-search-btn" type="button">SEARCH</button>
      <button class="ctx-btn" id="trace-back-btn" type="button">BACK</button>
    </div>
  `;

  menu.querySelector('#trace-clear-btn').onclick = removeInquiryPanel;
  menu.querySelector('#trace-back-btn').onclick = showInquiryMenu;
  menu.querySelector('#trace-find-btn').onclick = () => {
    renderInquiryForm('Find Function', 'trace.term', [
      { key: 'query', label: 'Function / keyword name', placeholder: 'required', required: true },
      { key: 'path', label: 'Scope file path' }
    ]);
  };
  menu.querySelector('#trace-search-btn').onclick = () => {
    renderInquiryForm('Global Search', 'search.term', [
      { key: 'query', label: 'Search query string', placeholder: 'required', required: true },
      { key: 'path', label: 'Scope file path' }
    ]);
  };
}

function renderInquiryForm(title, request, fields) {
  const panel = document.getElementById('aux-ctx-menu');
  if (!panel) return;

  panel.className = 'Menu-Cx inquiry-deck-panel is-form';
  panel.innerHTML = `
    <div class="inquiry-tree-head">
      <span>${escHtml(title)}</span>
      <button class="inquiry-clear-btn" type="button" id="form-clear-btn">CLR</button>
    </div>
    <div class="inquiry-form">
      ${fields.map(field => {
        return `
          <label class="inquiry-form-row">
            <span class="inquiry-form-label">${escHtml(field.label)}</span>
            <input class="inquiry-tree-input inquiry-form-input" type="text" data-key="${escAttr(field.key)}" placeholder="${escAttr(field.placeholder || '')}" />
          </label>
        `;
      }).join('')}
      <div class="inquiry-form-actions">
        <button class="ctx-btn" id="form-run-btn" type="button">RUN</button>
        <button class="ctx-btn" id="form-back-btn" type="button">BACK</button>
      </div>
      <div class="inquiry-form-note" id="form-error-note"></div>
    </div>
  `;

  const run = () => {
    const params = {};
    let missing = '';

    fields.forEach(field => {
      const value = (panel.querySelector(`.inquiry-form-input[data-key="${cssEscape(field.key)}"]`)?.value || '').trim();

      if (field.required && !value) {
        missing = field.label;
      }

      if (value) {
        params[field.key] = value;
      }
    });

    if (missing) {
      panel.querySelector('#form-error-note').textContent = `${missing} is required`;
      return;
    }

    submitInquiryPacket({ request, ...params });
  };

  panel.querySelector('#form-clear-btn').onclick = removeInquiryPanel;
  panel.querySelector('#form-back-btn').onclick = showInquiryMenu;
  panel.querySelector('#form-run-btn').onclick = run;
  panel.querySelectorAll('.inquiry-form-input').forEach(input => {
    input.onkeydown = event => {
      if (event.key === 'Enter') run();
    };
  });
  panel.querySelector('.inquiry-form-input')?.focus();
}

// ─────────────────────────────────────────────────────────────
// Status + Inquiry Submit (Posts straight to auxio's retrieve)
// ─────────────────────────────────────────────────────────────

export function setInquiryPanelStatus(mode, text) {
  const panel = document.getElementById('aux-ctx-menu') || document.createElement('div');
  panel.id = 'aux-ctx-menu';
  panel.className = `Menu-Cx inquiry-deck-panel is-${mode}`;
  panel.innerHTML = `
    <div class="inquiry-status-logo"></div>
    <div class="inquiry-status-text">${escHtml(text)}</div>
    <button class="inquiry-clear-btn" type="button" id="status-clear-btn">CLR</button>
  `;

  panel.querySelector('#status-clear-btn').onclick = removeInquiryPanel;
  mountInquiryPanel(panel);
}

async function submitInquiryPacket(packet) {
  if (!packet) return null;

  setInquiryPanelStatus('loading', 'Retrieving Context Details...');

  try {
    const reply = await retrieve(packet);
    setInquiryPanelStatus('ready', 'Context ready in LINE IN');
    return reply;
  } catch (error) {
    setInquiryPanelStatus('failed', error?.message || 'Context request failed');
    return null;
  }
}

// ─────────────────────────────────────────────────────────────
// Transport Button Binding
// ─────────────────────────────────────────────────────────────

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', bindDirectTransportKeys);
} else {
  bindDirectTransportKeys();
}

function bindDirectTransportKeys() {
  document.querySelectorAll('.Btn-Eo[data-action]').forEach(btn => {
    if (btn.dataset.auxMenuBound === 'true') return;
    btn.dataset.auxMenuBound = 'true';

    btn.addEventListener('click', event => {
      const action = String(btn.dataset.action || '').trim().toLowerCase();

      if (action !== 'scan' && action !== 'prev') {
        return;
      }

      event.preventDefault();
      showInquiryMenu();
    });
  });
}

// ─────────────────────────────────────────────────────────────
// Escaping
// ─────────────────────────────────────────────────────────────

function escHtml(value = '') {
  return String(value || '')
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;');
}

function escAttr(value = '') {
  return escHtml(value)
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

function cssEscape(value = '') {
  if (window.CSS?.escape) return window.CSS.escape(String(value));
  return String(value).replace(/"/g, '\\"');
}