// src/core/security/DefaultSpawnPolicy.ts

import type {
  ISpawnPolicyService,
  ISpawnRequest,
  ISpawnDecision,
  ISpawnPolicyRules,
} from './ISpawnPolicyService';

/**
 * Default spawn policy - allows all spawns.
 *
 * For development and testing. Use a custom policy
 * with rules for production deployments.
 */
export class DefaultSpawnPolicy implements ISpawnPolicyService {
  private readonly _rules: ISpawnPolicyRules;

  constructor(rules?: Partial<ISpawnPolicyRules>) {
    this._rules = {
      defaultTrustLevel: 'user',
      ...rules,
    };
  }

  evaluate(request: ISpawnRequest): ISpawnDecision {
    // Check denied types
    if (this._rules.deniedTypes?.includes(request.componentType)) {
      return {
        allowed: false,
        reason: `Component type '${request.componentType}' is not allowed`,
      };
    }

    // Check allowed types (if specified, only these are allowed)
    if (
      this._rules.allowedTypes &&
      !this._rules.allowedTypes.includes(request.componentType)
    ) {
      return {
        allowed: false,
        reason: `Component type '${request.componentType}' is not in allowed list`,
      };
    }

    // Sanitize props if configured
    let modifiedProps: Record<string, unknown> | undefined;
    if (this._rules.sanitizeProps && request.props) {
      modifiedProps = { ...request.props };
      for (const prop of this._rules.sanitizeProps) {
        delete modifiedProps[prop];
      }
    }

    return {
      allowed: true,
      modifiedProps,
      assignedContext: this._rules.defaultTrustLevel,
    };
  }
}

/**
 * Strict spawn policy - denies all spawns by default.
 *
 * Must explicitly allow component types.
 */
export class StrictSpawnPolicy implements ISpawnPolicyService {
  private readonly _allowedTypes: Set<string>;

  constructor(allowedTypes: string[] = []) {
    this._allowedTypes = new Set(allowedTypes);
  }

  evaluate(request: ISpawnRequest): ISpawnDecision {
    if (!this._allowedTypes.has(request.componentType)) {
      return {
        allowed: false,
        reason: `Component type '${request.componentType}' is not allowed in strict mode`,
      };
    }

    return {
      allowed: true,
      assignedContext: 'verified',
    };
  }

  /**
   * Add a component type to the allowed list.
   */
  allow(componentType: string): void {
    this._allowedTypes.add(componentType);
  }

  /**
   * Remove a component type from the allowed list.
   */
  deny(componentType: string): void {
    this._allowedTypes.delete(componentType);
  }
}
