/**
 * Agent-specific type definitions
 * Types for autonomous agents with tools, memory, and constraints
 */

import type { Contract, ExecutionContext } from '../../base/types'
import type { ResourceDefinition } from '../../../../platform/registry/types'
import type { AgentResourceEntry } from '../../../../organization-model/domains/resources'
import { Tool } from '../../tools/types'
import type { AgentMemory } from '../memory/types'
import type { LLMAdapter } from '../../llm/types'
import type { ModelConfig } from '../../llm/model-info'
import { AgentScopedLogger } from '../observability/logging'
import { MemoryManager } from '../memory/manager'
import type { ResourceMetricsConfig } from '../../../../operations/observability/types'
import type { KnowledgeMap } from '../knowledge-map/types'
import type { ExecutionInterface } from '../../interface/types'

// Re-export memory types for backward compatibility
export type { AgentMemory }

/**
 * Factory function for creating LLM adapters.
 * Injected into the Agent class to decouple the engine from server-only provider SDKs.
 * - API process: provides createLLMAdapter (real SDKs + process.env API keys)
 * - SDK worker: provides PostMessageLLMAdapter (proxies via platform.call)
 *
 * Uses `any` for optional params so both the real createLLMAdapter (with typed
 * AIUsageCollector/AICallContext) and the worker proxy (which ignores them) satisfy the type.
 */
export type LLMAdapterFactory = (
  config: ModelConfig,
  ...args: any[]
) => LLMAdapter

export type AgentKind = 'orchestrator' | 'specialist' | 'utility' | 'platform'

// Agent configuration
export interface AgentConfig extends ResourceDefinition {
  type: 'agent'
  /** OM descriptor backing canonical identity and governance metadata. */
  resource?: AgentResourceEntry
  kind: AgentKind

  // Agent behavior
  systemPrompt: string // System prompt defining agent behavior

  // Execution constraints (simplified for v1)
  constraints?: AgentConstraints

  /**
   * Session capability declaration (opt-in)
   * If true, agent is designed for multi-turn session interactions
   * Controls whether agent can use message action and appears in Sessions UI
   *
   * Use for:
   * - Conversational agents with multi-turn interactions
   * - Agents requiring persistent context across turns
   * - Agents that need human-in-the-loop communication
   */
  sessionCapable?: boolean

  /**
   * Security level for system prompt hardening (auto-derived if omitted)
   *
   * - 'standard': Lightweight defense (3 rules) - default for non-session agents
   * - 'hardened': Comprehensive defense (6 rules) - default for session-capable agents
   * - 'none': No security prompt - for pure internal agents with no external input
   *
   * If omitted, derived from sessionCapable:
   *   sessionCapable: true  -> 'hardened'
   *   sessionCapable: false -> 'standard'
   */
  securityLevel?: 'standard' | 'hardened' | 'none'

  /**
   * Memory management preferences (opt-in)
   * If provided, agent can use memoryOps to manage session memory
   * If omitted, agent has no memory management capabilities
   *
   * Agent-specific guidance on what to preserve, when to persist, and what to clean up.
   * This guidance is injected into the system prompt when memory management is enabled.
   *
   * Use for:
   * - Conversational agents needing cross-turn context
   * - Agents managing complex user preferences
   * - Agents tracking decisions over multiple iterations
   */
  memoryPreferences?: string

  // Lifecycle callbacks for observability (optional) - DEFERRED
}

export type DescriptorBackedAgentConfig = Omit<AgentConfig, 'resourceId' | 'type' | 'resource'> & {
  resource: AgentResourceEntry
}

// Execution constraints to prevent runaway agents
export interface AgentConstraints {
  // Agent execution control
  maxIterations?: number // Prevent infinite loops
  timeout?: number // Execution time limit (ms)

  // Memory constraints
  maxSessionMemoryKeys?: number // Max session memory keys (default: 10)
  maxMemoryTokens?: number // Total token budget for all memory (default: 14000)
}

// Agent definition - pure configuration without instance state
// Used by registry to define agents that can be instantiated with fresh memory
export interface AgentDefinition {
  config: AgentConfig
  contract: Contract
  tools: Tool[]

  /**
   * Model configuration for LLM execution
   * Specifies provider, API key, and model-specific options
   */
  modelConfig: ModelConfig

  /**
   * Optional knowledge map for lazy-loading capabilities
   * Enables agents to navigate organizational knowledge on-demand
   */
  knowledgeMap?: KnowledgeMap

  /**
   * Preload memory before execution starts
   * Handles BOTH context loading AND session restoration
   *
   * @param context - Execution context (includes sessionId if session turn)
   * @returns Initial AgentMemory state (sessionMemory entries + optionally history)
   */
  preloadMemory?: (context: ExecutionContext) => Promise<AgentMemory> | AgentMemory

  /**
   * Metrics configuration for ROI calculations
   * Optional: Only needed if tracking automation savings
   */
  metricsConfig?: ResourceMetricsConfig

  /**
   * Execution interface configuration (optional)
   * If provided, agent appears in Execution Runner UI
   */
  interface?: ExecutionInterface
}

/**
 * Agent execution context
 * Groups all state needed for agent execution phases
 */
export interface IterationContext {
  config: AgentConfig
  contract: Contract
  toolRegistry: Map<string, Tool>
  memoryManager: MemoryManager
  executionContext: ExecutionContext
  iteration: number
  logger: AgentScopedLogger
  modelConfig: ModelConfig
  adapterFactory: LLMAdapterFactory
  knowledgeMap?: KnowledgeMap
}
