import { z } from 'zod';
import { OpenApiService } from '../services/openapi-service';
import { safeStringify } from '../utils/json-utils';

export const getOpenApiOperationsTool = {
    name: 'get_openapi_operations',
    description: `Gets detailed information about operations for a specific endpoint in an OpenAPI schema.
  
  This tool retrieves comprehensive details about all HTTP methods (operations) available for
  a specific endpoint path in an OpenAPI schema, including parameters, request bodies,
  responses and other metadata.
    ## Parameters:
  - schemaUrl: [Required] URL where the OpenAPI schema is published or the API base URL (will auto-discover the schema)
  - path: [Required] The specific API path to get operations for (e.g., "/pets" or "/users/{id}")
  - authType: [Optional] Authentication method if the schema requires auth: 'bearer', 'basic', 'interactive', or 'none'
  - authConfig: [Optional] Authentication configuration object (required if authType is not 'none')
    - token: Bearer token (required for authType='bearer')
    - username: Username (required for authType='basic')
    - password: Password (optional for authType='basic')
    - clientId: Client ID (required for authType='interactive')
    - tenantId: Tenant ID (optional for authType='interactive', defaults to 'common')
    
  ## Example usage:
  - get_openapi_operations({
      schemaUrl: "https://petstore.swagger.io/v2/swagger.json",
      path: "/pets"
    })
  `,
    parameters: {
        schemaUrl: z.string().describe('URL where the OpenAPI schema is published'),
        path: z.string().describe('The specific API path to get operations for (e.g., "/pets")'),
        authType: z.enum(['bearer', 'basic', 'interactive', 'none']).default('none').describe('Authentication method if the schema requires auth'),
        authConfig: z.object({
            token: z.string().optional().describe('Bearer token for token-based authentication'),
            username: z.string().optional().describe('Username for basic authentication'),
            password: z.string().optional().describe('Password for basic authentication'),
            // For interactive auth
            clientId: z.string().optional().describe('Client ID for interactive authentication'),
            tenantId: z.string().optional().describe('Tenant ID for interactive authentication (defaults to "common")'),
            authority: z.string().optional().describe('Authority URL for authentication'),
            scopes: z.array(z.string()).optional().describe('Scopes required for API access'),
            redirectUri: z.string().optional().describe('Redirect URI for authentication callback')
        }).optional().describe('Authentication configuration')
    },
    handler: async ({ schemaUrl, path, authType, authConfig }: {
        schemaUrl: string;
        path: string;
        authType?: 'bearer' | 'basic' | 'interactive' | 'none';
        authConfig?: {
            token?: string;
            username?: string;
            password?: string;
            // For interactive auth
            clientId?: string;
            tenantId?: string;
            authority?: string;
            scopes?: string[];
            redirectUri?: string;
        };
    }) => {
        try {
            const operations = await OpenApiService.getOperations(schemaUrl, path, authType, authConfig);

            // Format the operations for better readability
            const formattedOperations = operations.map(op => {
                return {
                    method: op.method,
                    operationId: op.operationId || '',
                    summary: op.summary || '',
                    description: op.description || '',
                    parameters: op.parameters || [],
                    requestBody: op.requestBody || null,
                    responses: op.responses || {},
                    tags: op.tags || []
                };
            }); 
            return {
                content: [{
                    type: 'text',
                    text: safeStringify(formattedOperations)
                } as const]
            };
        } catch (error: any) {
            console.error('Error fetching OpenAPI operations:', error);
            return {
                content: [{
                    type: 'text',
                    text: `Error fetching OpenAPI operations: ${error.message || 'Unknown error'}`
                } as const],
                isError: true
            };
        }
    }
};
