// src/framework/components.ts

const FrameworkElementBase = HTMLElement;

function definePrimitiveTag(tag: string) {
  const registry = globalThis.customElements;
  if (!registry) return undefined;

  const existing = registry.get(tag);
  if (existing) return existing;

  const ElementBase = globalThis.HTMLElement ?? FrameworkElementBase;
  const PrimitiveTag = class extends ElementBase {};
  registry.define(tag, PrimitiveTag);
  return PrimitiveTag;
}

/**
 * Matrix Interface tag
 * Used to declare an interface implemented by a component
 *
 * Example:
 * ```html
 * <mx-interface name="DbService">
 *   {
 *     "name": "DbService",
 *     "version": "1.0.0",
 *     "methods": {
 *       "query": {
 *         "name": "query",
 *         "params": [
 *           { "name": "sql", "type": "string" }
 *         ],
 *         "returns": { "type": "array", "async": true }
 *       }
 *     }
 *   }
 * </mx-interface>
 * ```
 */
class MxInterface extends FrameworkElementBase {
  static define() {
    return definePrimitiveTag('mx-interface');
  }
}

/**
 * Matrix Contract tag
 * Used to declare channels for a component
 *
 * Example:
 * ```html
 * <mx-contract name="DataProvider">
 *   {
 *     "name": "DataProvider",
 *     "accepts": ["fetchData", "refreshCache"],
 *     "emits": ["dataChanged", "cacheUpdated"]
 *   }
 * </mx-contract>
 * ```
 */
class MxContract extends FrameworkElementBase {
  static define() {
    return definePrimitiveTag('mx-contract');
  }
}

/**
 * Matrix Proxy tag
 * Legacy / low-level alias for declaring a remote pseudo-child.
 *
 * Example:
 * ```html
 * <mx-proxy id="orders" mount="services.orders"></mx-proxy>
 * ```
 */
class MxProxy extends FrameworkElementBase {
  static define() {
    return definePrimitiveTag('mx-proxy');
  }
}

/**
 * Matrix Service tag (canonical DSL for remote endpoints)
 * Used to declare a remote service dependency as a phantom child
 *
 * Example:
 * ```html
 * <mx-service id="dbService" mount="db" type="remote">
 *   {
 *     "name": "DbService",
 *     "methods": {
 *       "query": { "params": [{"name": "sql", "type": "string"}], "async": true }
 *     }
 *   }
 * </mx-service>
 * ```
 */
class MxService extends FrameworkElementBase {
  static define() {
    return definePrimitiveTag('mx-service');
  }
}

/**
 * Matrix Middlewares tag
 * Namespacing container for middleware components. Children of this tag
 * participate in mount derivation so that, for example:
 *
 * ```html
 * <mx-middlewares id="middleware">
 *   <orders-logging-middleware id="logging"></orders-logging-middleware>
 * </mx-middlewares>
 * ```
 *
 * under a component mounted at app.orders will result in the
 * child being mounted at app.orders.middleware.logging.
 */
class MxMiddlewares extends FrameworkElementBase {
  static define() {
    return definePrimitiveTag('mx-middlewares');
  }
}

// Define all components
export function defineComponents() {
  MxInterface.define();
  MxContract.define();
  MxProxy.define();
  MxService.define();
  MxMiddlewares.define();
}

// Export component classes for manual definition
export { MxInterface, MxContract, MxProxy, MxService, MxMiddlewares };

// Re-export reusable leaf components from ./components/
export { MxTopicTag } from './components/MxTopicTag';
