/**
 * VL Case JSON Parser
 * Extracts component tree with compIds from VL IDE case JSON.
 * These compIds map to DOM attributes in the rendered app,
 * enabling precise selector-based testing.
 */

/**
 * Parse a case JSON object and extract the component tree.
 * @param {object} caseJson - The full case JSON { case, stage, server }
 * @returns {{ appName, components, interactiveElements, componentTree }}
 */
export function parseCaseJson(caseJson) {
  const caseMeta = caseJson.case || {};
  const stage = caseJson.stage || {};
  const appName = caseMeta.uis?.name || 'Unknown';

  const components = [];
  const interactiveElements = [];

  function walk(node, path = '', sectionName = '') {
    if (!node || typeof node !== 'object') return;

    const uis = node.uis || {};
    const name = uis.name || '';
    const compId = uis.compId || '';
    const nodeId = node.id || '';
    const type = node.type || '';
    const props = node.props || {};
    const currentPath = path ? `${path}/${name || type}` : (name || type);

    // Track section context (data-codeFragment = VL Section/Component)
    const curSection = type === 'data-codeFragment' ? name : sectionName;

    // Determine element category
    const isVisual = type.startsWith('ih5-native');
    const isButton = type === 'ih5-nativeButton';
    const isInput = type === 'ih5-nativeInput';
    const isTextarea = type === 'ih5-nativeTextarea';
    const isSelect = type === 'ih5-nativeSelect';
    const isText = type === 'ih5-nativeText';
    const isTag = type === 'ih5-nativeTag';
    const isRow = type === 'ih5-nativeRow';
    const isCol = type === 'ih5-nativeCol';
    const isPage = type === 'ih5-page';
    const isBanner = type === 'ih5-nativeBanner'; // Modal/overlay
    const isVar = type === 'data-var';
    const isIf = type === 'data-if';

    const component = {
      name,
      compId,
      nodeId,
      type,
      path: currentPath,
      section: curSection,
    };

    // Extract useful props
    if (props.value !== undefined) component.value = String(props.value);
    if (props.text !== undefined) component.text = String(props.text);
    if (props.placeholder) component.placeholder = props.placeholder;
    if (props.type) component.inputType = props.type;
    if (props.className) component.className = props.className;
    if (props.tag) component.htmlTag = props.tag;
    if (props.pagePath !== undefined) component.pagePath = props.pagePath;
    if (props.pageCustomId) component.pageCustomId = props.pageCustomId;

    // Only track meaningful components (not every wrapper div)
    if (name && (compId || isButton || isInput || isTextarea || isSelect || isText || isBanner || isPage || isVar || isIf || type === 'data-codeFragment')) {
      components.push(component);
    }

    // Track interactive elements specifically
    if (isButton || isInput || isTextarea || isSelect) {
      const el = {
        name,
        compId,
        nodeId,
        type: isButton ? 'button' : isInput ? 'input' : isTextarea ? 'textarea' : 'select',
        section: curSection,
      };
      if (props.value !== undefined) el.label = String(props.value);
      if (props.placeholder) el.placeholder = props.placeholder;
      if (props.type) el.inputType = props.type;
      if (props.className) el.className = props.className;
      interactiveElements.push(el);
    }

    // Recurse into children
    for (const child of (node.children || [])) {
      walk(child, currentPath, curSection);
    }
  }

  walk(stage);

  // Build a condensed component tree for LLM prompt (token-efficient)
  const componentTree = buildCondensedTree(stage);

  return {
    appName,
    components,
    interactiveElements,
    componentTree,
  };
}

/**
 * Build a condensed tree representation for LLM prompts.
 * Focuses on structure and interactive elements, skipping pure wrappers.
 */
function buildCondensedTree(stage) {
  const lines = [];

  function walk(node, depth = 0) {
    if (!node || typeof node !== 'object') return;
    const uis = node.uis || {};
    const name = uis.name || '';
    const compId = uis.compId || '';
    const type = node.type || '';
    const props = node.props || {};

    // Skip internal/system nodes
    if (type === 'data-wrap' || type === 'data-event' || type === 'data-obj-arr' || type === 'data-animate') return;

    const indent = '  '.repeat(Math.min(depth, 10));
    const parts = [];

    // Determine display type
    let displayType = '';
    if (type === 'ih5-nativeButton') displayType = 'Button';
    else if (type === 'ih5-nativeInput') displayType = 'Input';
    else if (type === 'ih5-nativeTextarea') displayType = 'Textarea';
    else if (type === 'ih5-nativeSelect') displayType = 'Select';
    else if (type === 'ih5-nativeText') displayType = 'Text';
    else if (type === 'ih5-nativeTag') displayType = 'Tag';
    else if (type === 'ih5-nativeRow') displayType = 'Row';
    else if (type === 'ih5-nativeCol') displayType = 'Col';
    else if (type === 'ih5-nativeImg') displayType = 'Img';
    else if (type === 'ih5-nativeBanner') displayType = 'Modal';
    else if (type === 'ih5-page') displayType = 'Page';
    else if (type === 'ih5-stage') displayType = 'Stage';
    else if (type === 'data-codeFragment') displayType = 'Section';
    else if (type === 'data-var') displayType = 'Var';
    else if (type === 'data-if') displayType = 'If';
    else if (type === 'ih5-system') displayType = 'System';
    else displayType = type;

    if (!name && !compId && depth > 2) {
      // Skip unnamed deep wrappers, but recurse
      for (const child of (node.children || [])) walk(child, depth);
      return;
    }

    parts.push(`${indent}${name || '?'} [${displayType}]`);
    if (compId) parts.push(`compId="${compId}"`);
    if (props.value !== undefined) parts.push(`label="${String(props.value).slice(0, 40)}"`);
    if (props.placeholder) parts.push(`placeholder="${props.placeholder}"`);
    if (props.type) parts.push(`inputType="${props.type}"`);
    if (props.className) parts.push(`class="${props.className}"`);

    lines.push(parts.join(' '));

    for (const child of (node.children || [])) {
      walk(child, depth + 1);
    }
  }

  walk(stage);
  return lines.join('\n');
}

/**
 * Extract a flat list of interactive elements suitable for LLM test generation.
 * This is the most token-efficient format.
 * @param {object} parsed - Result from parseCaseJson()
 * @returns {string} Formatted element list
 */
export function formatElementsForPrompt(parsed) {
  const lines = [];
  lines.push(`App: ${parsed.appName}`);
  lines.push('');

  // Group by section
  const bySection = {};
  for (const el of parsed.interactiveElements) {
    const section = el.section || '_root';
    if (!bySection[section]) bySection[section] = [];
    bySection[section].push(el);
  }

  for (const [section, els] of Object.entries(bySection)) {
    if (section !== '_root') lines.push(`## ${section}`);
    for (const el of els) {
      const parts = [`- ${el.name} (${el.type})`];
      if (el.compId) parts.push(`compId="${el.compId}"`);
      if (el.label) parts.push(`label="${el.label}"`);
      if (el.placeholder) parts.push(`placeholder="${el.placeholder}"`);
      if (el.inputType) parts.push(`inputType="${el.inputType}"`);
      lines.push(parts.join(' '));
    }
    lines.push('');
  }

  return lines.join('\n');
}

/**
 * Download case JSON from VL editor API.
 * @param {number|string} nid - The case nid
 * @param {string} cookie - Auth cookie
 * @returns {object} The case JSON
 */
export async function downloadCaseJson(nid, cookie) {
  const url = `https://editor.visuallogic.ai/edtfn/getcase?nid=${nid}`;
  const response = await fetch(url, {
    headers: cookie ? { Cookie: cookie } : {},
  });
  if (!response.ok) {
    throw new Error(`Failed to download case JSON (nid=${nid}): HTTP ${response.status}`);
  }
  const result = await response.json();
  if (result.code !== 0) {
    throw new Error(`Failed to download case JSON (nid=${nid}): code ${result.code}, ${result.message || ''}`);
  }
  return result.data || result;
}
