import { BaseNode } from './BaseNode.js';

/**
 * AST node for type definitions
 * Represents: definition User { ... }
 */
export class DefinitionNode extends BaseNode {
  constructor(name, definitionType = 'type', location = null) {
    super('Definition', location);
    this.name = name;
    this.definitionType = definitionType; // 'type', 'interface', etc.
    this.fields = [];
    this.behaviors = new Map(); // field name -> behavior
    this.cacheDirectives = new Map(); // field name -> cache directive
  }

  /**
   * Add a field to the definition
   * @param {FieldNode} field - Field to add
   */
  addField(field) {
    this.fields.push(field);
    this.addChild(field);
  }

  /**
   * Set behavior for a field
   * @param {string} fieldName - Name of the field
   * @param {BehaviorNode} behavior - Behavior to set
   */
  setBehavior(fieldName, behavior) {
    this.behaviors.set(fieldName, behavior);
  }

  /**
   * Set cache directive for a field
   * @param {string} fieldName - Name of the field
   * @param {string} directive - Cache directive ('lazy')
   */
  setCacheDirective(fieldName, directive) {
    if (directive === 'eager') {
      if (!DefinitionNode._warnedEagerCacheDirective) {
        DefinitionNode._warnedEagerCacheDirective = true;
        console.warn('[DefinitionNode] CACHE eager is deprecated; treating as CACHE lazy.');
      }
      this.cacheDirectives.set(fieldName, 'lazy');
      return;
    }
    this.cacheDirectives.set(fieldName, directive);
  }

  /**
   * Get behavior for a field
   * @param {string} fieldName - Name of the field
   * @returns {BehaviorNode|null} Behavior or null
   */
  getBehavior(fieldName) {
    return this.behaviors.get(fieldName) || null;
  }

  /**
   * Get cache directive for a field
   * @param {string} fieldName - Name of the field
   * @returns {string|null} Cache directive or null
   */
  getCacheDirective(fieldName) {
    return this.cacheDirectives.get(fieldName) || null;
  }

  /**
   * Find a field by name
   * @param {string} fieldName - Name to search for
   * @returns {FieldNode|null} Found field or null
   */
  getField(fieldName) {
    return this.fields.find(field => field.name === fieldName) || null;
  }

  /**
   * Get all fields with a specific type
   * @param {string} type - Type to filter by
   * @returns {FieldNode[]} Filtered fields
   */
  getFieldsOfType(type) {
    return this.fields.filter(field => field.type === type);
  }

  /**
   * Validate the definition
   * @returns {string[]} Array of error messages
   */
  validate() {
    const errors = [];

    // Check for duplicate field names
    const fieldNames = new Set();
    this.fields.forEach(field => {
      if (fieldNames.has(field.name)) {
        errors.push(`Duplicate field name '${field.name}' in definition '${this.name}'`);
      } else {
        fieldNames.add(field.name);
      }
    });

    // Validate each field
    this.fields.forEach(field => {
      const fieldErrors = field.validate ? field.validate() : [];
      errors.push(...fieldErrors);
    });

    return errors;
  }

  toString() {
    return `Definition(${this.name}: ${this.fields.length} fields)`;
  }
}
