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

/**
 * AST node for evidence definitions
 * Represents: evidence canRead(user: User, doc: Document) { ... } PROVIDES string
 */
export class EvidenceNode extends BaseNode {
  constructor(name, location = null) {
    super('Evidence', location);
    this.name = name;
    this.parameters = [];
    this.returnType = null;
    this.body = null; // EvidenceBodyNode
    this.provides = null; // Return type specification
  }

  /**
   * Add a parameter to the evidence
   * @param {ParameterNode} parameter - Parameter to add
   */
  addParameter(parameter) {
    this.parameters.push(parameter);
    this.addChild(parameter);
  }

  /**
   * Set the body of the evidence
   * @param {EvidenceBodyNode} body - Evidence body
   */
  setBody(body) {
    this.body = body;
    this.addChild(body);
  }

  /**
   * Set the return type for this evidence
   * @param {string} returnType - Return type
   */
  setReturnType(returnType) {
    this.returnType = returnType;
    this.provides = returnType;
  }

  /**
   * Get the parameter names as an array
   * @returns {string[]} Array of parameter names
   */
  getParameterNames() {
    return this.parameters.map(param => param.name);
  }

  /**
   * Get the parameter types as an array
   * @returns {string[]} Array of parameter types
   */
  getParameterTypes() {
    return this.parameters.map(param => param.type);
  }

  /**
   * Find a parameter by name
   * @param {string} name - Parameter name to find
   * @returns {ParameterNode|null} Found parameter or null
   */
  getParameter(name) {
    return this.parameters.find(param => param.name === name) || null;
  }

  /**
   * Get the signature string for this evidence
   * @returns {string} Evidence signature
   */
  getSignature() {
    const paramStr = this.parameters.map(param => `${param.name}: ${param.type}`).join(', ');
    return `${this.name}(${paramStr})`;
  }

  /**
   * Check if this evidence has a return type
   * @returns {boolean} True if has return type
   */
  hasReturnType() {
    return this.returnType !== null;
  }

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

    // Validate evidence name
    if (!this.name || typeof this.name !== 'string') {
      errors.push(`Invalid evidence name: ${this.name}`);
    }

    // Validate parameters
    this.parameters.forEach((param, index) => {
      const paramErrors = param.validate ? param.validate() : [];
      errors.push(...paramErrors.map(err => `Parameter ${index + 1}: ${err}`));
    });

    // Validate body
    if (this.body) {
      const bodyErrors = this.body.validate ? this.body.validate() : [];
      errors.push(...bodyErrors);
    }

    return errors;
  }

  toString() {
    const providesStr = this.returnType ? ` PROVIDES ${this.returnType}` : '';
    return `Evidence(${this.getSignature()}${providesStr})`;
  }
}
