import { z } from 'zod';

// ── Tool Definition ─────────────────────────────────────────
// Tools are registered globally and bound to agent versions via toolBindings[].

export const ToolParameterSchema = z.object({
  name: z.string().min(1),
  type: z.enum(['string', 'number', 'boolean', 'object', 'array']),
  description: z.string().optional(),
  required: z.boolean().default(false),
});

export const ToolDefinitionSchema = z.object({
  name: z.string().min(1),
  description: z.string().min(1),
  parameters: z.array(ToolParameterSchema).default([]),
  requiresReview: z.boolean().default(false),
  riskLevel: z.enum(['low', 'medium', 'high', 'critical']).default('low'),
});

export type ToolDefinition = z.infer<typeof ToolDefinitionSchema>;

export type ToolExecuteFn = (
  params: Record<string, unknown>,
  context: ToolExecutionContext
) => Promise<ToolExecutionResult>;

export interface ToolExecutionContext {
  runId: string;
  productId: string;
  agentId: string;
  userId: string;
}

export interface ToolExecutionResult {
  success: boolean;
  output?: unknown;
  error?: string;
  tokenUsage?: { prompt: number; completion: number; total: number };
}

interface RegisteredTool {
  definition: ToolDefinition;
  execute: ToolExecuteFn;
}

// ── Global Tool Registry ────────────────────────────────────

const tools = new Map<string, RegisteredTool>();

export function registerTool(definition: ToolDefinition, execute: ToolExecuteFn): void {
  tools.set(definition.name, { definition, execute });
}

export function getTool(name: string): RegisteredTool | undefined {
  return tools.get(name);
}

export function listTools(): ToolDefinition[] {
  return Array.from(tools.values()).map(t => t.definition);
}

export function getToolsForBindings(bindings: string[]): RegisteredTool[] {
  return bindings.map(name => tools.get(name)).filter((t): t is RegisteredTool => t !== undefined);
}

export function clearTools(): void {
  tools.clear();
}

// ── Validate tool bindings ──────────────────────────────────

export function validateToolBindings(bindings: string[]): {
  valid: string[];
  invalid: string[];
} {
  const valid: string[] = [];
  const invalid: string[] = [];
  for (const name of bindings) {
    if (tools.has(name)) {
      valid.push(name);
    } else {
      invalid.push(name);
    }
  }
  return { valid, invalid };
}
