function stripTypes(code, format) {
    if (format === 'ts')
        return code;
    return (code
        .replace(/\s+as\s+\w+(?:\[\])?/g, '')
        .replace(/\((\w+):\s*\w+\)/g, '($1)')
        .replace(/\((\w+):\s*any\)/g, '($1)')
        .replace(/Promise<void>\[\]/g, 'Promise[]')
        .replace(/Promise<void>/g, 'Promise')
        .replace(/:\s*TransitionEvent/g, ''));
}
const COMMAND_IMPLEMENTATIONS_TS = {
    toggle: `
    case 'toggle': {
      const className = getClassName(cmd.args[0]) || String(await evaluate(cmd.args[0], ctx));
      const targets = await getTarget();
      for (const el of targets) el.classList.toggle(className);
      ctx.it = targets.length === 1 ? targets[0] : targets;
      return ctx.it;
    }`,
    add: `
    case 'add': {
      const className = getClassName(cmd.args[0]) || String(await evaluate(cmd.args[0], ctx));
      const targets = await getTarget();
      for (const el of targets) el.classList.add(className);
      ctx.it = targets.length === 1 ? targets[0] : targets;
      return ctx.it;
    }`,
    remove: `
    case 'remove': {
      const targets = await getTarget();
      for (const el of targets) el.remove();
      return null;
    }`,
    removeClass: `
    case 'removeClass': {
      const className = getClassName(cmd.args[0]) || String(await evaluate(cmd.args[0], ctx));
      const targets = await getTarget();
      for (const el of targets) el.classList.remove(className);
      return targets;
    }`,
    show: `
    case 'show': {
      const targets = await getTarget();
      for (const el of targets) {
        (el as HTMLElement).style.display = '';
        el.classList.remove('hidden');
      }
      return targets;
    }`,
    hide: `
    case 'hide': {
      const targets = await getTarget();
      for (const el of targets) (el as HTMLElement).style.display = 'none';
      return targets;
    }`,
    set: `
    case 'set': {
      const target = cmd.args[0];
      const value = await evaluate(cmd.args[1], ctx);

      if (target.type === 'variable') {
        const varName = target.name.slice(1);
        const map = target.scope === 'local' ? ctx.locals : globalVars;
        map.set(varName, value);
        ctx.it = value;
        return value;
      }

      if (target.type === 'possessive' || target.type === 'member') {
        const obj = await evaluate(target.object, ctx);
        if (obj) {
          if (obj instanceof Element && isStyleProp(target.property)) {
            setStyleProp(obj, target.property, value);
          } else {
            (obj as any)[target.property] = value;
          }
          ctx.it = value;
          return value;
        }
      }

      ctx.it = value;
      return value;
    }`,
    get: `
    case 'get': {
      const value = await evaluate(cmd.args[0], ctx);
      ctx.it = value;
      return value;
    }`,
    wait: `
    case 'wait': {
      const duration = await evaluate(cmd.args[0], ctx);
      const ms = typeof duration === 'number' ? duration : parseInt(String(duration));
      await new Promise(resolve => setTimeout(resolve, ms));
      return ms;
    }`,
    transition: `
    case 'transition': {
      const property = String(await evaluate(cmd.args[0], ctx)).replace(/^\\*/, '');
      const toValue = await evaluate(cmd.args[1], ctx);
      const durationVal = await evaluate(cmd.args[2], ctx);
      const duration = typeof durationVal === 'number' ? durationVal :
                       String(durationVal).endsWith('ms') ? parseInt(String(durationVal)) :
                       String(durationVal).endsWith('s') ? parseFloat(String(durationVal)) * 1000 :
                       parseInt(String(durationVal)) || 300;

      const targets = await getTarget();
      const promises: Promise<void>[] = [];

      for (const el of targets) {
        const htmlEl = el as HTMLElement;
        const kebabProp = property.replace(/([A-Z])/g, '-$1').toLowerCase();

        const oldTransition = htmlEl.style.transition;
        htmlEl.style.transition = \`\${kebabProp} \${duration}ms ease\`;
        htmlEl.style.setProperty(kebabProp, String(toValue));

        promises.push(new Promise<void>(resolve => {
          const cleanup = () => {
            htmlEl.style.transition = oldTransition;
            resolve();
          };

          const onEnd = (e: TransitionEvent) => {
            if (e.propertyName === kebabProp) {
              htmlEl.removeEventListener('transitionend', onEnd);
              cleanup();
            }
          };

          htmlEl.addEventListener('transitionend', onEnd);
          setTimeout(cleanup, duration + 50);
        }));
      }

      await Promise.all(promises);
      ctx.it = targets.length === 1 ? targets[0] : targets;
      return ctx.it;
    }`,
    go: `
    case 'go': {
      const dest = await evaluate(cmd.args[0], ctx);
      const d = String(dest).toLowerCase();
      if (d === 'back') history.back();
      else if (d === 'forward') history.forward();
      else if (d === 'bottom') ctx.me.scrollIntoView({ block: 'end', behavior: 'smooth' });
      else if (d === 'top') ctx.me.scrollIntoView({ block: 'start', behavior: 'smooth' });
      else window.location.href = String(dest);
      return null;
    }`,
    call: `
    case 'call': {
      const result = await evaluate(cmd.args[0], ctx);
      ctx.it = result;
      return result;
    }`,
    log: `
    case 'log': {
      const values = await Promise.all(cmd.args.map((a: any) => evaluate(a, ctx)));
      console.log(...values);
      return values[0];
    }`,
    send: `
    case 'send': {
      const eventName = await evaluate(cmd.args[0], ctx);
      const targets = await getTarget();
      const event = new CustomEvent(String(eventName), { bubbles: true, detail: ctx.it });
      for (const el of targets) el.dispatchEvent(event);
      ctx.it = event;
      return event;
    }`,
    trigger: `
    case 'trigger': {
      const eventName = await evaluate(cmd.args[0], ctx);
      const targets = await getTarget();
      const event = new CustomEvent(String(eventName), { bubbles: true, detail: ctx.it });
      for (const el of targets) el.dispatchEvent(event);
      ctx.it = event;
      return event;
    }`,
    put: `
    case 'put': {
      const content = await evaluate(cmd.args[0], ctx);
      const modifier = cmd.modifier || 'into';

      if (cmd.target?.type === 'possessive' && isStyleProp(cmd.target.property)) {
        const obj = await evaluate(cmd.target.object, ctx);
        const elements = toElementArray(obj);
        for (const el of elements) {
          setStyleProp(el, cmd.target.property, content);
        }
        ctx.it = content;
        return content;
      }

      const targets = await getTarget();
      for (const el of targets) {
        const html = String(content);
        if (modifier === 'into') el.innerHTML = html;
        else if (modifier === 'before') el.insertAdjacentHTML('beforebegin', html);
        else if (modifier === 'after') el.insertAdjacentHTML('afterend', html);
        else if (modifier === 'at start of') el.insertAdjacentHTML('afterbegin', html);
        else if (modifier === 'at end of') el.insertAdjacentHTML('beforeend', html);
      }
      ctx.it = content;
      return content;
    }`,
    append: `
    case 'append': {
      const content = await evaluate(cmd.args[0], ctx);
      const targets = await getTarget();
      for (const el of targets) el.insertAdjacentHTML('beforeend', String(content));
      ctx.it = content;
      return content;
    }`,
    take: `
    case 'take': {
      const className = getClassName(await evaluate(cmd.args[0], ctx));
      const from = cmd.target ? await getTarget() : [ctx.me.parentElement!];
      for (const container of from) {
        const siblings = container.querySelectorAll('.' + className);
        siblings.forEach(el => el.classList.remove(className));
      }
      ctx.me.classList.add(className);
      return ctx.me;
    }`,
    increment: `
    case 'increment': {
      const target = cmd.args[0];
      const amount = cmd.args[1] ? await evaluate(cmd.args[1], ctx) : 1;

      if (target.type === 'variable') {
        const varName = target.name.slice(1);
        const map = target.scope === 'local' ? ctx.locals : globalVars;
        const current = map.get(varName) || 0;
        const newVal = current + amount;
        map.set(varName, newVal);
        ctx.it = newVal;
        return newVal;
      }

      const elements = toElementArray(await evaluate(target, ctx));
      for (const el of elements) {
        const current = parseFloat(el.textContent || '0') || 0;
        const newVal = current + amount;
        el.textContent = String(newVal);
        ctx.it = newVal;
      }
      return ctx.it;
    }`,
    decrement: `
    case 'decrement': {
      const target = cmd.args[0];
      const amount = cmd.args[1] ? await evaluate(cmd.args[1], ctx) : 1;

      if (target.type === 'variable') {
        const varName = target.name.slice(1);
        const map = target.scope === 'local' ? ctx.locals : globalVars;
        const current = map.get(varName) || 0;
        const newVal = current - amount;
        map.set(varName, newVal);
        ctx.it = newVal;
        return newVal;
      }

      const elements = toElementArray(await evaluate(target, ctx));
      for (const el of elements) {
        const current = parseFloat(el.textContent || '0') || 0;
        const newVal = current - amount;
        el.textContent = String(newVal);
        ctx.it = newVal;
      }
      return ctx.it;
    }`,
    focus: `
    case 'focus': {
      const targets = await getTarget();
      for (const el of targets) (el as HTMLElement).focus();
      return targets;
    }`,
    blur: `
    case 'blur': {
      const targets = await getTarget();
      for (const el of targets) (el as HTMLElement).blur();
      return targets;
    }`,
    return: `
    case 'return': {
      const value = cmd.args[0] ? await evaluate(cmd.args[0], ctx) : ctx.it;
      throw { type: 'return', value };
    }`,
    break: `
    case 'break': {
      throw { type: 'break' };
    }`,
    continue: `
    case 'continue': {
      throw { type: 'continue' };
    }`,
};
const BLOCK_IMPLEMENTATIONS_TS = {
    if: `
    case 'if': {
      const condition = await evaluate(block.condition!, ctx);
      if (condition) {
        return executeSequenceWithBlocks(block.body, ctx);
      } else if (block.elseBody) {
        return executeSequenceWithBlocks(block.elseBody, ctx);
      }
      return null;
    }`,
    repeat: `
    case 'repeat': {
      const count = await evaluate(block.condition!, ctx);
      const n = typeof count === 'number' ? count : parseInt(String(count));
      for (let i = 0; i < n && i < MAX_LOOP_ITERATIONS; i++) {
        ctx.locals.set('__loop_index__', i);
        ctx.locals.set('__loop_count__', i + 1);
        try {
          await executeSequenceWithBlocks(block.body, ctx);
        } catch (e: any) {
          if (e?.type === 'break') break;
          if (e?.type === 'continue') continue;
          throw e;
        }
      }
      return null;
    }`,
    for: `
    case 'for': {
      const { variable, iterable } = block.condition as any;
      const items = await evaluate(iterable, ctx);
      const arr = Array.isArray(items) ? items : items instanceof NodeList ? Array.from(items) : [items];
      const varName = variable.startsWith(':') ? variable.slice(1) : variable;
      for (let i = 0; i < arr.length && i < MAX_LOOP_ITERATIONS; i++) {
        ctx.locals.set(varName, arr[i]);
        ctx.locals.set('__loop_index__', i);
        ctx.locals.set('__loop_count__', i + 1);
        try {
          await executeSequenceWithBlocks(block.body, ctx);
        } catch (e: any) {
          if (e?.type === 'break') break;
          if (e?.type === 'continue') continue;
          throw e;
        }
      }
      return null;
    }`,
    while: `
    case 'while': {
      let iterations = 0;
      while (await evaluate(block.condition!, ctx) && iterations < MAX_LOOP_ITERATIONS) {
        ctx.locals.set('__loop_index__', iterations);
        try {
          await executeSequenceWithBlocks(block.body, ctx);
        } catch (e: any) {
          if (e?.type === 'break') break;
          if (e?.type === 'continue') { iterations++; continue; }
          throw e;
        }
        iterations++;
      }
      return null;
    }`,
    fetch: `
    case 'fetch': {
      const { url, responseType } = block.condition as any;
      try {
        const urlVal = await evaluate(url, ctx);
        const response = await fetch(String(urlVal));
        if (!response.ok) throw new Error(\`HTTP \${response.status}\`);

        const resType = await evaluate(responseType, ctx);
        let data: any;
        if (resType === 'json') data = await response.json();
        else if (resType === 'html') {
          const text = await response.text();
          const doc = new DOMParser().parseFromString(text, 'text/html');
          data = doc.body.innerHTML;
        } else data = await response.text();

        ctx.it = data;
        ctx.locals.set('it', data);
        ctx.locals.set('result', data);
        ctx.locals.set('response', response);

        await executeSequenceWithBlocks(block.body, ctx);
      } catch (error: any) {
        if (error?.type === 'return') throw error;
        ctx.locals.set('error', error);
        console.error('Fetch error:', error);
      }
      return null;
    }`,
};
const STYLE_COMMANDS = ['set', 'put', 'increment', 'decrement'];
const ELEMENT_ARRAY_COMMANDS = ['put', 'increment', 'decrement'];
function getCommandImplementations(format = 'ts') {
    const result = {};
    for (const [name, code] of Object.entries(COMMAND_IMPLEMENTATIONS_TS)) {
        result[name] = stripTypes(code, format);
    }
    return result;
}
function getBlockImplementations(format = 'ts') {
    const result = {};
    for (const [name, code] of Object.entries(BLOCK_IMPLEMENTATIONS_TS)) {
        result[name] = stripTypes(code, format);
    }
    return result;
}
function getAvailableCommands() {
    return Object.keys(COMMAND_IMPLEMENTATIONS_TS);
}
function getAvailableBlocks() {
    return Object.keys(BLOCK_IMPLEMENTATIONS_TS);
}
const COMMAND_IMPLEMENTATIONS = COMMAND_IMPLEMENTATIONS_TS;
const BLOCK_IMPLEMENTATIONS = BLOCK_IMPLEMENTATIONS_TS;

function generateBundleCode(config) {
    const { name, commands, blocks = [], htmxIntegration = false, globalName = 'hyperfixi', positionalExpressions = false, parserImportPath = '../parser/hybrid', autoInit = true, esModule = true, format = 'ts', maxLoopIterations = 1000, } = config;
    const needsStyleHelpers = commands.some(cmd => STYLE_COMMANDS.includes(cmd));
    const needsElementArrayHelper = commands.some(cmd => ELEMENT_ARRAY_COMMANDS.includes(cmd));
    const hasBlocks = blocks.length > 0;
    const hasReturn = commands.includes('return');
    const commandImpls = getCommandImplementations(format);
    const blockImpls = getBlockImplementations(format);
    const commandCases = commands
        .filter(cmd => commandImpls[cmd])
        .map(cmd => commandImpls[cmd])
        .join('\n');
    const blockCases = blocks
        .filter(block => blockImpls[block])
        .map(block => blockImpls[block])
        .join('\n');
    return `/**
 * HyperFixi ${name} Bundle (Auto-Generated)
 *
 * Generated by: @lokascript/core bundle-generator
 * Commands: ${commands.join(', ')}${blocks.length > 0 ? `\n * Blocks: ${blocks.join(', ')}` : ''}${positionalExpressions ? '\n * Positional expressions: enabled' : ''}
 *
 * DO NOT EDIT - Regenerate with the build script.
 */

// =============================================================================
// MODULAR PARSER IMPORTS
// =============================================================================

import { HybridParser } from '${parserImportPath}/parser-core';
import type { ASTNode, CommandNode, EventNode${hasBlocks ? ', BlockNode' : ''} } from '${parserImportPath}/ast-types';

// =============================================================================
// RUNTIME
// =============================================================================

interface Context {
  me: Element;
  event?: Event;
  it?: any;
  you?: Element;
  locals: Map<string, any>;
}

const globalVars = new Map<string, any>();
${hasBlocks ? `const MAX_LOOP_ITERATIONS = ${maxLoopIterations};` : ''}

async function evaluate(node: ASTNode, ctx: Context): Promise<any> {
  switch (node.type) {
    case 'literal': return node.value;

    case 'identifier':
      if (node.value === 'me' || node.value === 'my') return ctx.me;
      if (node.value === 'it') return ctx.it;
      if (node.value === 'you') return ctx.you;
      if (node.value === 'event') return ctx.event;
      if (node.value === 'body') return document.body;
      if (node.value === 'document') return document;
      if (node.value === 'window') return window;
      if (ctx.locals.has(node.value)) return ctx.locals.get(node.value);
      if (node.value in (ctx.me as any)) return (ctx.me as any)[node.value];
      return node.value;

    case 'variable':
      if (node.scope === 'local') return ctx.locals.get(node.name.slice(1));
      const gName = node.name.slice(1);
      if (globalVars.has(gName)) return globalVars.get(gName);
      return (window as any)[node.name];

    case 'selector':
      const elements = document.querySelectorAll(node.value);
      return elements.length === 1 ? elements[0] : Array.from(elements);

    case 'binary':
      return evaluateBinary(node, ctx);

    case 'possessive':
    case 'member':
      const obj = await evaluate(node.object, ctx);
      if (obj == null) return undefined;
      const prop = node.computed ? await evaluate(node.property, ctx) : node.property;
      return obj[prop];

    case 'call': {
      let callContext: any = null;
      let callee: any;

      if (node.callee.type === 'member' || node.callee.type === 'possessive') {
        callContext = await evaluate(node.callee.object, ctx);
        const p = node.callee.computed
          ? await evaluate(node.callee.property, ctx)
          : node.callee.property;
        callee = callContext?.[p];
      } else {
        callee = await evaluate(node.callee, ctx);
      }

      const args = await Promise.all(node.args.map((a: ASTNode) => evaluate(a, ctx)));
      if (typeof callee === 'function') return callee.apply(callContext, args);
      return undefined;
    }
${positionalExpressions
        ? `
    case 'positional':
      return evaluatePositional(node, ctx);
`
        : ''}
    default: return undefined;
  }
}

async function evaluateBinary(node: ASTNode, ctx: Context): Promise<any> {
  if (node.operator === 'has') {
    const left = await evaluate(node.left, ctx);
    if (left instanceof Element && node.right.type === 'selector' && node.right.value.startsWith('.')) {
      return left.classList.contains(node.right.value.slice(1));
    }
    return false;
  }

  const left = await evaluate(node.left, ctx);
  const right = await evaluate(node.right, ctx);

  switch (node.operator) {
    case '+': return left + right;
    case '-': return left - right;
    case '*': return left * right;
    case '/': return left / right;
    case '%': return left % right;
    case '==': case 'is': return left == right;
    case '!=': case 'is not': return left != right;
    case '<': return left < right;
    case '>': return left > right;
    case '<=': return left <= right;
    case '>=': return left >= right;
    case 'and': case '&&': return left && right;
    case 'or': case '||': return left || right;
    case 'contains': case 'includes':
      if (typeof left === 'string') return left.includes(right);
      if (Array.isArray(left)) return left.includes(right);
      if (left instanceof Element) return left.contains(right);
      return false;
    case 'matches':
      if (left instanceof Element) return left.matches(right);
      if (typeof left === 'string') return new RegExp(right).test(left);
      return false;
    default: return undefined;
  }
}
${positionalExpressions
        ? `
function evaluatePositional(node: ASTNode, ctx: Context): Element | null {
  const target = node.target;
  let elements: Element[] = [];

  let selector: string | null = null;
  if (target.type === 'selector') {
    selector = target.value;
  } else if (target.type === 'identifier') {
    selector = target.value;
  } else if (target.type === 'htmlSelector') {
    selector = target.value;
  }
  if (selector) {
    elements = Array.from(document.querySelectorAll(selector));
  }

  switch (node.position) {
    case 'first': return elements[0] || null;
    case 'last': return elements[elements.length - 1] || null;
    case 'next': return ctx.me.nextElementSibling;
    case 'previous': return ctx.me.previousElementSibling;
    case 'closest': return target.value ? ctx.me.closest(target.value) : null;
    case 'parent': return ctx.me.parentElement;
    default: return elements[0] || null;
  }
}
`
        : ''}
// =============================================================================
// COMMAND EXECUTOR
// =============================================================================

${needsStyleHelpers
        ? `
const isStyleProp = (prop: string) => prop?.startsWith('*');
const getStyleName = (prop: string) => prop.substring(1);
const setStyleProp = (el: Element, prop: string, value: any): boolean => {
  if (!isStyleProp(prop)) return false;
  (el as HTMLElement).style.setProperty(getStyleName(prop), String(value));
  return true;
};
`
        : ''}

${needsElementArrayHelper
        ? `
const toElementArray = (val: any): Element[] => {
  if (Array.isArray(val)) return val.filter(e => e instanceof Element);
  if (val instanceof Element) return [val];
  if (typeof val === 'string') return Array.from(document.querySelectorAll(val));
  return [];
};
`
        : ''}

async function executeCommand(cmd: CommandNode, ctx: Context): Promise<any> {
  const getTarget = async (): Promise<Element[]> => {
    if (!cmd.target) return [ctx.me];
    const t = await evaluate(cmd.target, ctx);
    if (Array.isArray(t)) return t;
    if (t instanceof Element) return [t];
    if (typeof t === 'string') return Array.from(document.querySelectorAll(t));
    return [ctx.me];
  };

  const getClassName = (node: any): string => {
    if (!node) return '';
    if (node.type === 'selector') return node.value.slice(1);
    if (node.type === 'string' || node.type === 'literal') {
      const val = node.value;
      return typeof val === 'string' && val.startsWith('.') ? val.slice(1) : String(val);
    }
    if (node.type === 'identifier') return node.value;
    return '';
  };

  switch (cmd.name) {
${commandCases}

    default:
      console.warn(\`${name} bundle: Unknown command '\${cmd.name}'\`);
      return null;
  }
}
${hasBlocks
        ? `
// =============================================================================
// BLOCK EXECUTOR
// =============================================================================

async function executeBlock(block: BlockNode, ctx: Context): Promise<any> {
  switch (block.type) {
${blockCases}

    default:
      console.warn(\`${name} bundle: Unknown block '\${block.type}'\`);
      return null;
  }
}
`
        : ''}
// =============================================================================
// SEQUENCE EXECUTOR
// =============================================================================

async function executeSequence(nodes: ASTNode[], ctx: Context): Promise<any> {
  let result: any;
  for (const node of nodes) {
    if (node.type === 'command') {
      result = await executeCommand(node as CommandNode, ctx);
    }${hasBlocks
        ? ` else if (['if', 'repeat', 'for', 'while', 'fetch'].includes(node.type)) {
      result = await executeBlock(node as BlockNode, ctx);
    }`
        : ''}
  }
  return result;
}
${hasBlocks
        ? `
async function executeSequenceWithBlocks(nodes: ASTNode[], ctx: Context): Promise<any> {
  try {
    return await executeSequence(nodes, ctx);
  } catch (e: any) {
    if (e?.type === 'return') throw e;
    throw e;
  }
}
`
        : ''}
async function executeAST(ast: ASTNode, me: Element, event?: Event): Promise<any> {
  const ctx: Context = { me, event, locals: new Map() };

  if (ast.type === 'sequence') {
    ${hasReturn || hasBlocks ? "try { return await executeSequence(ast.commands, ctx); } catch (e: any) { if (e?.type === 'return') return e.value; throw e; }" : 'return executeSequence(ast.commands, ctx);'}
  }

  if (ast.type === 'event') {
    const eventNode = ast as EventNode;
    const eventName = eventNode.event;

    if (eventName === 'init') {
      ${hasReturn || hasBlocks ? "try { await executeSequence(eventNode.body, ctx); } catch (e: any) { if (e?.type !== 'return') throw e; }" : 'await executeSequence(eventNode.body, ctx);'}
      return;
    }

    const target = eventNode.filter ? await evaluate(eventNode.filter, ctx) : me;
    const targetEl = target instanceof Element ? target : me;
    const mods = eventNode.modifiers;

    let handler = async (e: Event) => {
      if (mods.prevent) e.preventDefault();
      if (mods.stop) e.stopPropagation();

      const handlerCtx: Context = {
        me, event: e,
        you: e.target instanceof Element ? e.target : undefined,
        locals: new Map(),
      };
      ${hasReturn || hasBlocks ? "try { await executeSequence(eventNode.body, handlerCtx); } catch (err: any) { if (err?.type !== 'return') throw err; }" : 'await executeSequence(eventNode.body, handlerCtx);'}
    };

    if (mods.debounce) {
      let timeout: any;
      const orig = handler;
      handler = async (e: Event) => {
        clearTimeout(timeout);
        timeout = setTimeout(() => orig(e), mods.debounce);
      };
    }

    if (mods.throttle) {
      let lastCall = 0;
      const orig = handler;
      handler = async (e: Event) => {
        const now = Date.now();
        if (now - lastCall >= mods.throttle!) {
          lastCall = now;
          await orig(e);
        }
      };
    }

    targetEl.addEventListener(eventName, handler, { once: !!mods.once });
    return;
  }

  return null;
}

// =============================================================================
// DOM PROCESSOR
// =============================================================================

function processElement(el: Element): void {
  const code = el.getAttribute('_');
  if (!code) return;

  try {
    const parser = new HybridParser(code);
    const ast = parser.parse();
    executeAST(ast, el);
  } catch (err) {
    console.error('HyperFixi ${name} error:', err, 'Code:', code);
  }
}

function processElements(root: Element | Document = document): void {
  const elements = root.querySelectorAll('[_]');
  elements.forEach(processElement);
}

// =============================================================================
// PUBLIC API
// =============================================================================

const api = {
  version: '1.0.0-${name.toLowerCase().replace(/\s+/g, '-')}',

  parse(code: string): ASTNode {
    const parser = new HybridParser(code);
    return parser.parse();
  },

  async execute(code: string, element?: Element): Promise<any> {
    const me = element || document.body;
    const parser = new HybridParser(code);
    const ast = parser.parse();
    return executeAST(ast, me);
  },

  run: async (code: string, element?: Element) => api.execute(code, element),
  eval: async (code: string, element?: Element) => api.execute(code, element),

  init: processElements,
  process: processElements,

  commands: ${JSON.stringify(commands)},
  ${blocks.length > 0 ? `blocks: ${JSON.stringify(blocks)},` : ''}
  parserName: 'hybrid',
};

// =============================================================================
// AUTO-INITIALIZE
// =============================================================================
${autoInit
        ? `
if (typeof window !== 'undefined') {
  (window as any).${globalName} = api;
  (window as any)._hyperscript = api;

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => processElements());
  } else {
    processElements();
  }
${htmxIntegration
            ? `
  // HTMX integration
  document.addEventListener('htmx:afterSettle', (e: Event) => {
    const target = (e as CustomEvent).detail?.target;
    if (target) processElements(target);
  });
`
            : ''}
}
`
        : ''}
${esModule
        ? `
export default api;
export { api, processElements };
`
        : ''}`;
}
function generateBundle(config) {
    const warnings = [];
    const errors = [];
    const strict = config.validation?.strict ?? false;
    const unknownCommands = config.commands.filter(cmd => !COMMAND_IMPLEMENTATIONS[cmd]);
    for (const cmd of unknownCommands) {
        const error = {
            type: 'unknown-command',
            message: `Unknown command '${cmd}' will not be included`,
            name: cmd,
        };
        errors.push(error);
        warnings.push(error.message);
    }
    const unknownBlocks = (config.blocks || []).filter(block => !BLOCK_IMPLEMENTATIONS[block]);
    for (const block of unknownBlocks) {
        const error = {
            type: 'unknown-block',
            message: `Unknown block '${block}' will not be included`,
            name: block,
        };
        errors.push(error);
        warnings.push(error.message);
    }
    if (strict && errors.length > 0) {
        const errorMessages = errors.map(e => e.message).join('; ');
        throw new Error(`Bundle generation failed (strict mode): ${errorMessages}`);
    }
    const code = generateBundleCode(config);
    return {
        code,
        commands: config.commands.filter(cmd => COMMAND_IMPLEMENTATIONS[cmd]),
        blocks: (config.blocks || []).filter(block => BLOCK_IMPLEMENTATIONS[block]),
        positional: config.positionalExpressions || false,
        warnings,
        errors,
    };
}

const AVAILABLE_COMMANDS = [
    'toggle',
    'add',
    'remove',
    'removeClass',
    'show',
    'hide',
    'put',
    'append',
    'take',
    'set',
    'get',
    'increment',
    'decrement',
    'wait',
    'transition',
    'send',
    'trigger',
    'log',
    'call',
    'go',
    'focus',
    'blur',
    'return',
    'break',
    'continue',
];
const AVAILABLE_BLOCKS = ['if', 'repeat', 'for', 'while', 'fetch'];
const FULL_RUNTIME_ONLY_COMMANDS = [
    'async',
    'js',
    'make',
    'swap',
    'morph',
    'process-partials',
    'bind',
    'persist',
    'default',
    'beep',
    'tell',
    'copy',
    'pick',
    'push-url',
    'replace-url',
    'halt',
    'exit',
    'throw',
    'unless',
    'settle',
    'measure',
    'install',
];
function isAvailableCommand(command) {
    return AVAILABLE_COMMANDS.includes(command);
}
function isAvailableBlock(block) {
    return AVAILABLE_BLOCKS.includes(block);
}
function requiresFullRuntime(command) {
    return FULL_RUNTIME_ONLY_COMMANDS.includes(command);
}

export { AVAILABLE_BLOCKS, AVAILABLE_COMMANDS, BLOCK_IMPLEMENTATIONS, COMMAND_IMPLEMENTATIONS, ELEMENT_ARRAY_COMMANDS, FULL_RUNTIME_ONLY_COMMANDS, STYLE_COMMANDS, generateBundle, generateBundleCode, getAvailableBlocks, getAvailableCommands, getBlockImplementations, getCommandImplementations, isAvailableBlock, isAvailableCommand, requiresFullRuntime };
//# sourceMappingURL=index.mjs.map
