// src/serialization/toHtml.ts
// Serialize Matrix component to HTML representation
//
// HTML representation uses custom elements with data attributes
// to encode the component structure.
//
// Reference: Vision/14-HOMOICONIC-ARCHITECTURE.md, Vision/20-COMPOSITION-DSL.md

import type { IComponentSchema } from './IComponentSchema';
import type { ISerializationOptions } from './ISerializationOptions';

/**
 * Convert component schema to HTML representation
 *
 * @example
 * toHtml({ name: 'Button', accepts: { click: {} }, emits: { clicked: {} } })
 * // Returns:
 * // <matrix-button>
 * //   <mx-accepts method="click"></mx-accepts>
 * //   <mx-emits event="clicked"></mx-emits>
 * // </matrix-button>
 */
export function toHtml(
  schema: IComponentSchema,
  options: ISerializationOptions = {}
): string {
  const { pretty = true, includeComments = false, indent = '  ' } = options;
  const lines: string[] = [];

  // Convert component name to kebab-case element
  const tagName = `matrix-${toKebabCase(schema.name)}`;
  const attrs: string[] = [];

  if (schema.mount) {
    attrs.push(`mount="${escapeHtml(schema.mount)}"`);
  }

  // Opening tag
  const attrStr = attrs.length > 0 ? ' ' + attrs.join(' ') : '';
  lines.push(`<${tagName}${attrStr}>`);

  // Accepts (methods)
  for (const [name, method] of Object.entries(schema.accepts)) {
    const paramAttrs = Object.entries(method.params || {})
      .map(([pname, pschema]) => `${pname}="${pschema.type}${pschema.optional ? '?' : ''}"`)
      .join(' ');

    if (includeComments && method.description) {
      lines.push(`${indent}<!-- ${method.description} -->`);
    }

    lines.push(`${indent}<mx-accepts method="${name}"${paramAttrs ? ' ' + paramAttrs : ''}></mx-accepts>`);
  }

  // Emits (events)
  for (const [name, event] of Object.entries(schema.emits)) {
    const payloadAttrs = Object.entries(event.payload || {})
      .map(([pname, pschema]) => `${pname}="${pschema.type}${pschema.optional ? '?' : ''}"`)
      .join(' ');

    if (includeComments && event.description) {
      lines.push(`${indent}<!-- ${event.description} -->`);
    }

    lines.push(`${indent}<mx-emits event="${name}"${payloadAttrs ? ' ' + payloadAttrs : ''}></mx-emits>`);
  }

  // Children
  if (schema.children) {
    for (const child of schema.children) {
      const childHtml = toHtml(child, options);
      const childLines = childHtml.split('\n').map(line => indent + line);
      lines.push(...childLines);
    }
  }

  // Closing tag
  lines.push(`</${tagName}>`);

  return pretty ? lines.join('\n') : lines.join('');
}

/**
 * Convert camelCase/PascalCase to kebab-case
 */
function toKebabCase(str: string): string {
  return str
    .replace(/([a-z])([A-Z])/g, '$1-$2')
    .replace(/[\s_]+/g, '-')
    .toLowerCase();
}

/**
 * Escape HTML special characters
 */
function escapeHtml(str: string): string {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}
