/**
 * Base class for all tool packs.
 * Extend this to create a new pack with tools and apps.
 */

import { z } from 'zod';
import type { TwilioClient } from '../client.js';
import type { RegisteredTool, SafetyTier, ToolAnnotations, ToolResult } from '../tool-registry.js';
import { appResult } from '../apps/renderer.js';

export abstract class BasePack {
  protected client: TwilioClient;
  protected tools: RegisteredTool[] = [];

  /** Pack identifier (e.g., 'messaging', 'voice') */
  abstract readonly name: string;
  /** Human-readable description */
  abstract readonly description: string;
  /** Keywords for intent detection / lazy loading */
  abstract readonly keywords: string[];

  constructor(client: TwilioClient) {
    this.client = client;
  }

  /** Override this to register all tools in the pack */
  abstract setup(): void;

  /** Get all registered tools */
  getTools(): RegisteredTool[] {
    return this.tools;
  }

  /** Helper to register a tool with less boilerplate */
  protected registerTool(config: {
    name: string;
    description: string;
    category: string;
    safety: SafetyTier;
    annotations?: Partial<ToolAnnotations>;
    inputSchema: z.ZodType<any>;
    _meta?: {
      labels: {
        category: string;
        access: "read" | "write" | "delete";
        complexity: "simple" | "complex" | "batch";
      };
    };
    isApp?: boolean;
    tier?: 1 | 2;
    handler: (params: any) => Promise<ToolResult>;
  }): void {
    this.tools.push({
      name: config.name,
      description: config.description,
      category: config.category,
      pack: this.name,
      safety: config.safety,
      annotations: {
        readOnlyHint: config.safety === 'green',
        destructiveHint: false,
        idempotentHint: false,
        costHint: false,
        ...config.annotations,
      },
      inputSchema: config.inputSchema,
      _meta: config._meta,
      isApp: config.isApp ?? false,
      tier: config.tier ?? 2,
      handler: config.handler,
    });
  }

  /** Helper: return a text-only result */
  protected textResult(text: string, isError = false): ToolResult {
    return {
      content: [{ type: 'text', text }],
      isError,
    };
  }

  /** Helper: return an error result */
  protected errorResult(message: string): ToolResult {
    return this.textResult(`Error: ${message}`, true);
  }

  /** Helper: return a JSON result */
  protected jsonResult(data: any, summary?: string): ToolResult {
    const text = summary
      ? `${summary}\n\n${JSON.stringify(data, null, 2)}`
      : JSON.stringify(data, null, 2);
    return { content: [{ type: 'text', text }] };
  }

  /** Helper: return an MCP App (HTML) result */
  protected appResult(html: string, textFallback: string): ToolResult {
    return appResult(html, textFallback);
  }
}
