import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import {
  ApiResponse,
  ClientConfig,
  ConvertImageOptions,
  HealthStatus,
  ImageGenerationOptions,
  Metrics,
  OptimizeImageOptions,
  ResizeImageOptions,
  SupportedFormat,
  SupportedSize,
} from './types';

/**
 * AI Image Generator SDK Client
 *
 * A client for interacting with the AI Image Generator API
 */
export class AIImageGeneratorClient {
  private client: AxiosInstance;
  private baseUrl: string;

  /**
   * Create a new AI Image Generator client
   *
   * @param config - Configuration options for the client
   */
  constructor(config: ClientConfig) {
    this.baseUrl = config.baseUrl.endsWith('/')
      ? config.baseUrl.slice(0, -1)
      : config.baseUrl;

    const axiosConfig: AxiosRequestConfig = {
      baseURL: this.baseUrl,
      timeout: config.timeout || 30000,
      headers: {
        'Content-Type': 'application/json',
      },
    };

    if (config.apiKey) {
      axiosConfig.headers = {
        ...axiosConfig.headers,
        Authorization: `Bearer ${config.apiKey}`,
      };
    }

    this.client = axios.create(axiosConfig);
  }

  /**
   * Generate an image using AI
   *
   * @param options - Image generation options
   * @returns URL of the generated image
   */
  async generateImage(options: ImageGenerationOptions): Promise<string> {
    const params = new URLSearchParams();

    // Add required parameters
    params.append('width', options.width.toString());
    params.append('height', options.height.toString());
    params.append('prompt', options.prompt);

    // Add optional parameters if provided
    if (options.model) params.append('model', options.model);
    if (options.format) params.append('format', options.format);
    if (options.quality) params.append('quality', options.quality.toString());
    if (options.optimize !== undefined)
      params.append('optimize', options.optimize.toString());

    let endpoint = '/images/image-gen';

    try {
      const response = await this.client.get(endpoint, { params });
      return response.request.res.responseUrl || response.headers.location;
    } catch (error) {
      // If the first endpoint fails, try the alternative endpoint
      endpoint = '/images/image-gen';
      const response = await this.client.get(endpoint, { params });
      return response.request.res.responseUrl || response.headers.location;
    }
  }

  /**
   * Get a list of supported AI models
   *
   * @returns List of supported models
   */
  async getSupportedModels(): Promise<ApiResponse<string[]>> {
    const response = await this.client.get('/images/supported-models');
    console.log(response.data);
    return {
      data: response.data,
      status: response.status,
      statusText: response.statusText,
    };
  }

  /**
   * Get a list of supported image sizes
   *
   * @returns List of supported image sizes
   */
  async getSupportedSizes(): Promise<ApiResponse<SupportedSize[]>> {
    const response = await this.client.get('/images/supported-sizes');
    return {
      data: response.data,
      status: response.status,
      statusText: response.statusText,
    };
  }

  /**
   * Resize an existing image
   *
   * @param id - ID of the image to resize
   * @param options - Resize options
   * @returns URL of the resized image
   */
  async resizeImage(id: string, options: ResizeImageOptions): Promise<string> {
    const params = new URLSearchParams();

    params.append('width', options.width.toString());
    params.append('height', options.height.toString());
    params.append('format', options.format);
    params.append('quality', options.quality.toString());

    const response = await this.client.get(`/images/process/resize/${id}`, {
      params,
    });
    return response.request.res.responseUrl || response.headers.location;
  }

  /**
   * Convert an image to a different format
   *
   * @param id - ID of the image to convert
   * @param options - Conversion options
   * @returns URL of the converted image
   */
  async convertImage(
    id: string,
    options: ConvertImageOptions,
  ): Promise<string> {
    const params = new URLSearchParams();

    params.append('format', options.format);
    params.append('quality', options.quality.toString());

    const response = await this.client.get(`/images/process/convert/${id}`, {
      params,
    });
    return response.request.res.responseUrl || response.headers.location;
  }

  /**
   * Optimize an image for web delivery
   *
   * @param id - ID of the image to optimize
   * @param options - Optimization options
   * @returns URL of the optimized image
   */
  async optimizeImage(
    id: string,
    options: OptimizeImageOptions,
  ): Promise<string> {
    const params = new URLSearchParams();

    params.append('format', options.format);
    params.append('quality', options.quality.toString());

    const response = await this.client.get(`/images/process/optimize/${id}`, {
      params,
    });
    return response.request.res.responseUrl || response.headers.location;
  }

  /**
   * Get a list of supported image formats
   *
   * @returns List of supported image formats
   */
  async getSupportedFormats(): Promise<ApiResponse<SupportedFormat[]>> {
    const response = await this.client.get('/images/process/formats');
    return {
      data: response.data,
      status: response.status,
      statusText: response.statusText,
    };
  }

  /**
   * Get API metrics
   *
   * @returns API metrics
   */
  async getMetrics(): Promise<ApiResponse<Metrics>> {
    const response = await this.client.get('/monitoring/metrics');
    return {
      data: response.data,
      status: response.status,
      statusText: response.statusText,
    };
  }

  /**
   * Check API health
   *
   * @returns Health status
   */
  async checkHealth(): Promise<ApiResponse<HealthStatus>> {
    const response = await this.client.get('/monitoring/health');
    return {
      data: response.data,
      status: response.status,
      statusText: response.statusText,
    };
  }
}
