/**
 * ProxyModel Plugin Interface — code-based MCP middleware.
 *
 * Plugins intercept, modify, add, or block MCP requests and responses.
 * The gate, content-pipeline, and propose-prompt are all plugins.
 * With no plugin attached, the router is a transparent MCP proxy.
 */
import type { JsonRpcRequest, JsonRpcResponse } from '../types.js';
import type { LLMProvider, CacheProvider, StageLogger, Section, ToolDefinition, ContentType } from './types.js';
import type { AuditEvent } from '../audit/types.js';

// ── Plugin Session Context ──────────────────────────────────────────

/** Per-session context provided to plugin hooks. */
export interface PluginSessionContext {
  readonly sessionId: string;
  readonly projectName: string;
  /** Per-session mutable state (persists across requests in a session) */
  readonly state: Map<string, unknown>;

  // Platform services
  readonly llm: LLMProvider;
  readonly cache: CacheProvider;
  readonly log: StageLogger;

  // Virtual tool management
  registerTool(tool: ToolDefinition, handler: VirtualToolHandler): void;
  unregisterTool(name: string): void;

  // Virtual server management
  registerServer(server: VirtualServer): void;
  unregisterServer(name: string): void;

  // Notification queue
  queueNotification(method: string, params?: unknown): void;

  // Upstream access
  discoverTools(): Promise<ToolDefinition[]>;
  routeToUpstream(request: JsonRpcRequest): Promise<JsonRpcResponse>;

  // Prompt access
  fetchPromptIndex(): Promise<PromptIndexEntry[]>;
  getSystemPrompt(name: string, fallback: string): Promise<string>;

  // Content processing
  processContent(toolName: string, content: string, contentType: ContentType): Promise<{ content: string; sections?: Section[] }>;

  // mcpd client access (for propose_prompt, etc.)
  postToMcpd(path: string, body: Record<string, unknown>): Promise<unknown>;
  getFromMcpd(path: string): Promise<unknown>;

  // Audit event emission (auto-fills sessionId and projectName)
  emitAuditEvent(event: Omit<AuditEvent, 'sessionId' | 'projectName'>): void;
}

// ── Virtual Server ──────────────────────────────────────────────────

export type VirtualToolHandler = (args: Record<string, unknown>, ctx: PluginSessionContext) => Promise<unknown>;
export type VirtualResourceHandler = (params: Record<string, unknown>, ctx: PluginSessionContext) => Promise<unknown>;

export interface VirtualServer {
  name: string;
  description?: string;
  tools: Array<{
    definition: ToolDefinition;
    handler: VirtualToolHandler;
  }>;
  resources?: Array<{
    definition: ResourceDefinition;
    handler: VirtualResourceHandler;
  }>;
}

export interface ResourceDefinition {
  uri: string;
  name?: string;
  description?: string;
  mimeType?: string;
}

// ── Prompt Index Entry ──────────────────────────────────────────────

export interface PromptIndexEntry {
  name: string;
  priority: number;
  summary: string | null;
  chapters: string[] | null;
  content: string;
}

// ── Plugin Interface ────────────────────────────────────────────────

export interface ProxyModelPlugin {
  readonly name: string;
  readonly description?: string;
  /** Parent plugin names for composition. */
  readonly extends?: readonly string[];

  // Lifecycle hooks
  onSessionCreate?(ctx: PluginSessionContext): Promise<void>;
  onSessionDestroy?(ctx: PluginSessionContext): Promise<void>;

  // Initialize hook — can return additional instructions
  onInitialize?(request: JsonRpcRequest, ctx: PluginSessionContext): Promise<{ instructions?: string } | null>;

  // Tools hooks
  onToolsList?(tools: ToolDefinition[], ctx: PluginSessionContext): Promise<ToolDefinition[]>;
  onToolCallBefore?(toolName: string, args: Record<string, unknown>, request: JsonRpcRequest, ctx: PluginSessionContext): Promise<JsonRpcResponse | null>;
  onToolCallAfter?(toolName: string, args: Record<string, unknown>, response: JsonRpcResponse, ctx: PluginSessionContext): Promise<JsonRpcResponse>;

  // Resources hooks
  onResourcesList?(resources: ResourceDefinition[], ctx: PluginSessionContext): Promise<ResourceDefinition[]>;
  onResourceRead?(uri: string, request: JsonRpcRequest, ctx: PluginSessionContext): Promise<JsonRpcResponse | null>;

  // Prompts hooks
  onPromptsList?(prompts: Array<{ name: string; description?: string }>, ctx: PluginSessionContext): Promise<Array<{ name: string; description?: string }>>;
  onPromptGet?(name: string, request: JsonRpcRequest, ctx: PluginSessionContext): Promise<JsonRpcResponse | null>;
}

/** Factory function that creates a plugin instance, optionally with config. */
export type ProxyModelFactory = (config?: Record<string, unknown>) => ProxyModelPlugin;

/** All hook method names on ProxyModelPlugin (for conflict detection). */
export const PLUGIN_HOOK_NAMES = [
  'onSessionCreate',
  'onSessionDestroy',
  'onInitialize',
  'onToolsList',
  'onToolCallBefore',
  'onToolCallAfter',
  'onResourcesList',
  'onResourceRead',
  'onPromptsList',
  'onPromptGet',
] as const;

export type PluginHookName = (typeof PLUGIN_HOOK_NAMES)[number];
