/**
 * Widget registry for dependency injection.
 *
 * ⚠️ AUTO-GENERATED BY PRISM - DO NOT EDIT
 */

import type { Widget, WidgetKey, FieldType } from './types';
import { DEFAULT_WIDGETS, UI_WIDGET_MAP } from './defaults';
import { TextInput } from './components';

// Widget type with broader compatibility
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type AnyWidget = Widget<any>;

/**
 * Widget registry that supports multiple levels of customization.
 *
 * Resolution order:
 * 1. Model.field specific (e.g., "Customer.email")
 * 2. ui_widget hint (e.g., "ui:richtext")
 * 3. Field type default (e.g., "string")
 * 4. Fallback to TextInput
 */
export class WidgetRegistry {
  private widgets: Map<string, AnyWidget> = new Map();
  private defaults = DEFAULT_WIDGETS;
  private uiWidgets = UI_WIDGET_MAP;

  /**
   * Register a custom widget.
   *
   * @example
   * // Override all string fields
   * registry.register("string", MyCustomTextInput);
   *
   * // Override specific model.field
   * registry.register("Customer.email", EmailWithValidation);
   *
   * // Register new ui_widget type
   * registry.register("ui:address", AddressAutocomplete);
   */
  register(key: WidgetKey, widget: AnyWidget): void {
    this.widgets.set(key, widget);
  }

  /**
   * Bulk register widgets.
   */
  registerAll(widgets: Record<WidgetKey, AnyWidget>): void {
    Object.entries(widgets).forEach(([key, widget]) => {
      this.register(key, widget);
    });
  }

  /**
   * Get widget for a field.
   *
   * Resolution order:
   * 1. Model.field specific (e.g., "Customer.email")
   * 2. ui_widget hint (e.g., "ui:richtext")
   * 3. Field type default (e.g., "string")
   * 4. Fallback to TextInput
   */
  resolve(
    modelName: string,
    fieldName: string,
    fieldType: FieldType,
    uiWidget?: string
  ): AnyWidget {
    // 1. Check model.field specific override
    const specificKey = `${modelName}.${fieldName}`;
    if (this.widgets.has(specificKey)) {
      return this.widgets.get(specificKey)!;
    }

    // 2. Check ui_widget hint
    if (uiWidget) {
      const uiKey = `ui:${uiWidget}`;
      if (this.widgets.has(uiKey)) {
        return this.widgets.get(uiKey)!;
      }
      if (this.uiWidgets[uiWidget]) {
        return this.uiWidgets[uiWidget];
      }
    }

    // 3. Check field type override
    if (this.widgets.has(fieldType)) {
      return this.widgets.get(fieldType)!;
    }

    // 4. Return default for field type
    return this.defaults[fieldType] ?? TextInput;
  }

  /**
   * Create a scoped registry (for local overrides).
   */
  scoped(): WidgetRegistry {
    const scoped = new WidgetRegistry();
    scoped.widgets = new Map(this.widgets);
    return scoped;
  }
}

/** Global widget registry instance */
export const widgetRegistry = new WidgetRegistry();
