/**
 * LLM Request Builder
 * Constructs universal LLMRequest from execution context using modular prompt system
 */

import type { z } from 'zod'
import type { IterationContext } from '../core/types'
import type { ToolDefinition } from '../../tools/types'
import type { KnowledgeMap } from '../knowledge-map/types'
import { zodToJsonSchema } from '@alcyone-labs/zod-to-json-schema'
import { buildSecurityPrompt } from './prompt-sections/security'
import { buildBaseActionsPrompt } from './prompt-sections/base-actions'
import { buildKnowledgeMapPrompt } from './prompt-sections/knowledge-map'
import { buildToolsPrompt } from './prompt-sections/tools'
import { buildMemoryPrompt, type MemoryStatus } from './prompt-sections/memory'
import { buildCompletionPrompt } from './prompt-sections/completion'

/**
 * Options for system prompt generation
 */
export interface SystemPromptOptions {
  /** Security level for prompt injection defense */
  securityLevel: 'standard' | 'hardened' | 'none'
  /** Whether to include message action (session-based agents only) */
  includeMessageAction: boolean
  /** Whether to include navigate-knowledge action (knowledge map present) */
  includeNavigateKnowledge: boolean
  /** Knowledge map with nodes (optional) */
  knowledgeMap?: KnowledgeMap
  /** Available tools */
  tools: ToolDefinition[]
  /** Current memory status */
  memoryStatus: MemoryStatus
  /** Output schema for completion guidance (optional) */
  outputSchema?: z.ZodSchema
  /** Memory preferences for opt-in memory management (optional string) */
  memoryPreferences?: string
}

/**
 * Builds complete system prompt from modular sections
 *
 * Composition order:
 * 0. Security rules (standard/hardened, or omitted if 'none')
 * 1. Base actions (conditional message action based on session context)
 * 2. Knowledge map (if present)
 * 3. Tools (if present)
 * 4. Memory management (CONDITIONAL - only if preferences provided)
 * 5. Task completion
 * 6. Agent-specific instructions
 *
 * @param agentPrompt - Agent-specific instructions
 * @param options - Prompt configuration options
 * @returns Complete system prompt string
 */
function buildSystemPrompt(agentPrompt: string, options: SystemPromptOptions): string {
  const sections: string[] = []

  // 0. Security rules (first position for maximum LLM attention)
  const securitySection = buildSecurityPrompt(options.securityLevel)
  if (securitySection) {
    sections.push(securitySection)
  }

  // 1. Base actions (with conditional message and navigate-knowledge actions)
  sections.push(buildBaseActionsPrompt(options.includeMessageAction, options.includeNavigateKnowledge))

  // 2. Knowledge map (if present)
  const knowledgeMapSection = buildKnowledgeMapPrompt(options.knowledgeMap)
  if (knowledgeMapSection) {
    sections.push(knowledgeMapSection)
  }

  // 3. Tools (if present)
  const toolsSection = buildToolsPrompt(options.tools)
  if (toolsSection) {
    sections.push(toolsSection)
  }

  // 4. Memory management (CONDITIONAL - only if preferences provided)
  // Conservative approach: Keep memoryOps in schema, but skip prompt if no preferences
  if (options.memoryPreferences) {
    sections.push(buildMemoryPrompt(options.memoryStatus, options.memoryPreferences))
  }

  // 5. Task completion guidance (always included)
  sections.push(buildCompletionPrompt(options.outputSchema))

  // 6. Agent-specific instructions (separator + prompt)
  sections.push('---\n')
  sections.push('# AGENT-SPECIFIC INSTRUCTIONS\n\n')
  sections.push(agentPrompt)

  return sections.join('\n')
}

/**
 * Build universal LLM iteration request from current state
 * Combines system prompt, tools, constraints, and memory using modular prompt builder
 *
 * @param iterationContext - Agent execution context
 * @returns Agent iteration request data
 */
export function buildReasoningRequest(iterationContext: IterationContext): {
  systemPrompt: string
  tools: ToolDefinition[]
  constraints: { maxOutputTokens?: number; temperature?: number }
  memoryContext: string
  includeMessageAction: boolean
  includeNavigateKnowledge: boolean
  includeMemoryOps: boolean
} {
  // Build tool definitions for system prompt from registry
  const tools = Array.from(iterationContext.toolRegistry.values())
  const toolDefinitions = tools.map((tool) => ({
    name: tool.name,
    description: tool.description,
    inputSchema: zodToJsonSchema(tool.inputSchema as z.ZodSchema)
  }))

  // Get memory status for system prompt
  const memoryStatus = iterationContext.memoryManager.getStatus()

  // Agent capability: explicit session support declaration
  // Controls whether message action is available in prompts
  const isSessionCapable = !!iterationContext.config.sessionCapable

  // Detect knowledge map availability
  const hasKnowledgeMap = !!(
    iterationContext.knowledgeMap && Object.keys(iterationContext.knowledgeMap.nodes).length > 0
  )

  // Detect if memory operations should be included
  const includeMemoryOps = !!iterationContext.config.memoryPreferences

  // Derive security level: explicit config > sessionCapable-based default
  const securityLevel = iterationContext.config.securityLevel ?? (isSessionCapable ? 'hardened' : 'standard')

  // Build complete system prompt using modular builder
  const systemPrompt = buildSystemPrompt(iterationContext.config.systemPrompt, {
    securityLevel,
    includeMessageAction: isSessionCapable,
    includeNavigateKnowledge: hasKnowledgeMap,
    knowledgeMap: iterationContext.knowledgeMap,
    tools: toolDefinitions,
    memoryStatus,
    outputSchema: iterationContext.contract.outputSchema,
    memoryPreferences: iterationContext.config.memoryPreferences
  })

  // Enforce hard limits before building request
  iterationContext.memoryManager.enforceHardLimits()

  return {
    systemPrompt,
    tools: toolDefinitions,
    constraints: {
      maxOutputTokens: iterationContext.modelConfig.maxOutputTokens,
      temperature: 1
    },
    memoryContext: iterationContext.memoryManager.toContext(
      iterationContext.iteration,
      iterationContext.executionContext.sessionTurnNumber
    ),
    includeMessageAction: isSessionCapable,
    includeNavigateKnowledge: hasKnowledgeMap,
    includeMemoryOps
  }
}
