import { GHLApiClient } from '../clients/ghl-api-client.js';
import {
  MCPGetMediaFilesParams,
  MCPUploadMediaFileParams,
  MCPDeleteMediaParams,
  GHLGetMediaFilesRequest,
  GHLUploadMediaFileRequest,
  GHLDeleteMediaRequest
} from '../types/ghl-types.js';

export interface Tool {
  name: string;
  description: string;
  inputSchema: {
    type: string;
    properties: Record<string, any>;
    required: string[];
  };
}

/**
 * MediaTools class for GoHighLevel Media Library API endpoints
 * Handles file management operations including listing, uploading, and deleting files/folders
 */
export class MediaTools {
  constructor(private ghlClient: GHLApiClient) {}

  /**
   * Get all available Media Library tool definitions
   */
  getToolDefinitions(): Tool[] {
    return [
      {
        name: 'get_media_files',
        description: 'Get list of files and folders from the media library with filtering and search capabilities',
        inputSchema: {
          type: 'object',
          properties: {
            offset: { 
              type: 'number', 
              description: 'Number of files to skip in listing',
              minimum: 0
            },
            limit: { 
              type: 'number', 
              description: 'Number of files to show in the listing (max 100)',
              minimum: 1,
              maximum: 100
            },
            sortBy: { 
              type: 'string', 
              description: 'Field to sort the file listing by (e.g., createdAt, name, size)',
              default: 'createdAt'
            },
            sortOrder: { 
              type: 'string', 
              description: 'Direction to sort files (asc or desc)',
              enum: ['asc', 'desc'],
              default: 'desc'
            },
            type: { 
              type: 'string', 
              description: 'Filter by type (file or folder)',
              enum: ['file', 'folder']
            },
            query: { 
              type: 'string', 
              description: 'Search query text to filter files by name'
            },
            altType: { 
              type: 'string', 
              description: 'Context type (location or agency)',
              enum: ['location', 'agency'],
              default: 'location'
            },
            altId: { 
              type: 'string', 
              description: 'Location or Agency ID (uses default location if not provided)'
            },
            parentId: { 
              type: 'string', 
              description: 'Parent folder ID to list files within a specific folder'
            }
          },
          required: []
        }
      },
      {
        name: 'upload_media_file',
        description: 'Upload a file to the media library or add a hosted file URL (max 25MB for direct uploads)',
        inputSchema: {
          type: 'object',
          properties: {
            file: { 
              type: 'string', 
              description: 'File data (binary) for direct upload'
            },
            hosted: { 
              type: 'boolean', 
              description: 'Set to true if providing a fileUrl instead of direct file upload',
              default: false
            },
            fileUrl: { 
              type: 'string', 
              description: 'URL of hosted file (required if hosted=true)'
            },
            name: { 
              type: 'string', 
              description: 'Custom name for the uploaded file'
            },
            parentId: { 
              type: 'string', 
              description: 'Parent folder ID to upload file into'
            },
            altType: { 
              type: 'string', 
              description: 'Context type (location or agency)',
              enum: ['location', 'agency'],
              default: 'location'
            },
            altId: { 
              type: 'string', 
              description: 'Location or Agency ID (uses default location if not provided)'
            }
          },
          required: []
        }
      },
      {
        name: 'delete_media_file',
        description: 'Delete a specific file or folder from the media library',
        inputSchema: {
          type: 'object',
          properties: {
            id: { 
              type: 'string', 
              description: 'ID of the file or folder to delete'
            },
            altType: { 
              type: 'string', 
              description: 'Context type (location or agency)',
              enum: ['location', 'agency'],
              default: 'location'
            },
            altId: { 
              type: 'string', 
              description: 'Location or Agency ID (uses default location if not provided)'
            }
          },
          required: ['id']
        }
      }
    ];
  }

  /**
   * Execute a media tool by name with given arguments
   */
  async executeTool(name: string, args: any): Promise<any> {
    switch (name) {
      case 'get_media_files':
        return this.getMediaFiles(args as MCPGetMediaFilesParams);
      
      case 'upload_media_file':
        return this.uploadMediaFile(args as MCPUploadMediaFileParams);
      
      case 'delete_media_file':
        return this.deleteMediaFile(args as MCPDeleteMediaParams);
      
      default:
        throw new Error(`Unknown media tool: ${name}`);
    }
  }

  /**
   * GET MEDIA FILES
   */
  private async getMediaFiles(params: MCPGetMediaFilesParams = {}): Promise<{ success: boolean; files: any[]; total?: number; message: string }> {
    try {
      const requestParams: GHLGetMediaFilesRequest = {
        sortBy: params.sortBy || 'createdAt',
        sortOrder: params.sortOrder || 'desc',
        altType: params.altType || 'location',
        altId: params.altId || this.ghlClient.getConfig().locationId,
        ...(params.offset !== undefined && { offset: params.offset }),
        ...(params.limit !== undefined && { limit: params.limit }),
        ...(params.type && { type: params.type }),
        ...(params.query && { query: params.query }),
        ...(params.parentId && { parentId: params.parentId })
      };

      const response = await this.ghlClient.getMediaFiles(requestParams);
      
      if (!response.success || !response.data) {
        const errorMsg = response.error?.message || 'Unknown API error';
        throw new Error(`API request failed: ${errorMsg}`);
      }

      const files = Array.isArray(response.data.files) ? response.data.files : [];
      
      return {
        success: true,
        files,
        total: response.data.total,
        message: `Retrieved ${files.length} media files/folders`
      };
    } catch (error) {
      throw new Error(`Failed to get media files: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  /**
   * UPLOAD MEDIA FILE
   */
  private async uploadMediaFile(params: MCPUploadMediaFileParams): Promise<{ success: boolean; fileId: string; url?: string; message: string }> {
    try {
      // Validate upload parameters
      if (params.hosted && !params.fileUrl) {
        throw new Error('fileUrl is required when hosted=true');
      }
      if (!params.hosted && !params.file) {
        throw new Error('file is required when hosted=false or not specified');
      }

      const uploadData: GHLUploadMediaFileRequest = {
        altType: params.altType || 'location',
        altId: params.altId || this.ghlClient.getConfig().locationId,
        ...(params.hosted !== undefined && { hosted: params.hosted }),
        ...(params.fileUrl && { fileUrl: params.fileUrl }),
        ...(params.file && { file: params.file }),
        ...(params.name && { name: params.name }),
        ...(params.parentId && { parentId: params.parentId })
      };

      const response = await this.ghlClient.uploadMediaFile(uploadData);
      
      if (!response.success || !response.data) {
        const errorMsg = response.error?.message || 'Unknown API error';
        throw new Error(`API request failed: ${errorMsg}`);
      }
      
      return {
        success: true,
        fileId: response.data.fileId,
        url: response.data.url,
        message: `File uploaded successfully with ID: ${response.data.fileId}`
      };
    } catch (error) {
      throw new Error(`Failed to upload media file: ${error instanceof Error ? error.message : String(error)}`);
    }
  }

  /**
   * DELETE MEDIA FILE
   */
  private async deleteMediaFile(params: MCPDeleteMediaParams): Promise<{ success: boolean; message: string }> {
    try {
      const deleteParams: GHLDeleteMediaRequest = {
        id: params.id,
        altType: params.altType || 'location',
        altId: params.altId || this.ghlClient.getConfig().locationId
      };

      const response = await this.ghlClient.deleteMediaFile(deleteParams);
      
      if (!response.success) {
        const errorMsg = response.error?.message || 'Unknown API error';
        throw new Error(`API request failed: ${errorMsg}`);
      }
      
      return {
        success: true,
        message: `Media file/folder deleted successfully`
      };
    } catch (error) {
      throw new Error(`Failed to delete media file: ${error instanceof Error ? error.message : String(error)}`);
    }
  }
} 