/**
 * BaoLife AI Image Generation Module
 *
 * Handles automated image generation using multiple AI providers:
 * - Google Imagen 4 Ultra (primary, via fal.ai)
 * - FLUX 1.1 Pro (via fal.ai)
 * - DALL-E 3 (via OpenAI)
 *
 * Supports caching, queue management, and cozy cartoon style generation.
 * Ported from Python ws/image_generation.py
 */

import { config } from '../../config.js';

// ============================================================
// Types
// ============================================================

export type ImageProvider = 'imagen4' | 'flux' | 'dalle3';

export interface ImageGenerationResult {
  imageUrl: string | null;
  error: string | null;
}

export interface ImageGenerationOptions {
  style?: string;
  width?: number;
  height?: number;
  provider?: ImageProvider;
}

// ============================================================
// Constants
// ============================================================

/**
 * Style preset for cozy cartoon style (optimized for Imagen 4 Ultra)
 */
export const COZY_CARTOON_STYLE = `cozy cartoon style, illustration, warm colors,
friendly atmosphere, high quality digital art, clean lines,
--no words, text, letters, face`;

/**
 * Available style presets
 */
export const STYLE_PRESETS: Record<string, string> = {
  cozy_cartoon: COZY_CARTOON_STYLE,
  realistic: 'photorealistic, high detail, natural lighting',
  anime: 'anime style, vibrant colors, clean lines',
  pixel: 'pixel art style, retro, 16-bit aesthetic',
};

// ============================================================
// Image Generator Class
// ============================================================

export class ImageGenerator {
  private provider: ImageProvider;

  constructor(provider: ImageProvider = config.IMAGE_GENERATION_PROVIDER) {
    this.provider = provider;
  }

  /**
   * Generate an image using the configured provider
   */
  async generateImage(
    prompt: string,
    options: ImageGenerationOptions = {}
  ): Promise<ImageGenerationResult> {
    const {
      style = 'cozy_cartoon',
      width = 1024,
      height = 1024,
    } = options;

    const provider = options.provider ?? this.provider;

    switch (provider) {
      case 'dalle3':
        return this.generateDalle3(prompt, style, width, height);
      case 'flux':
        return this.generateFlux(prompt, style, width, height);
      case 'imagen4':
        return this.generateImagen4(prompt, style, width, height);
      default:
        return { imageUrl: null, error: `Unknown provider: ${provider}` };
    }
  }

  /**
   * Generate image using OpenAI DALL-E 3
   */
  private async generateDalle3(
    prompt: string,
    style: string,
    width: number,
    height: number
  ): Promise<ImageGenerationResult> {
    if (!config.OPENAI_API_KEY) {
      return { imageUrl: null, error: 'OpenAI API key not configured' };
    }

    try {
      const fullPrompt = this.applyStyle(prompt, style);

      // DALL-E 3 supports 1024x1024, 1024x1792, 1792x1024
      let size: string = '1024x1024';
      if (width === 1024 && height === 1792) {
        size = '1024x1792';
      } else if (width === 1792 && height === 1024) {
        size = '1792x1024';
      }

      console.log(`Generating DALL-E 3 image: ${fullPrompt.substring(0, 100)}...`);

      const response = await fetch('https://api.openai.com/v1/images/generations', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${config.OPENAI_API_KEY}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          model: 'dall-e-3',
          prompt: fullPrompt,
          size,
          quality: 'standard',
          n: 1,
        }),
      });

      if (!response.ok) {
        const errorText = await response.text();
        return { imageUrl: null, error: `DALL-E 3 API error ${response.status}: ${errorText}` };
      }

      const result = await response.json() as { data: Array<{ url: string }> };
      const imageUrl = result.data[0]?.url;

      if (imageUrl) {
        console.log(`DALL-E 3 image generated: ${imageUrl}`);
        return { imageUrl, error: null };
      }

      return { imageUrl: null, error: 'No image returned from DALL-E 3 API' };
    } catch (e) {
      const error = `DALL-E 3 generation failed: ${e instanceof Error ? e.message : String(e)}`;
      console.error(error);
      return { imageUrl: null, error };
    }
  }

  /**
   * Generate image using FLUX 1.1 Pro via fal.ai
   */
  private async generateFlux(
    prompt: string,
    style: string,
    width: number,
    height: number
  ): Promise<ImageGenerationResult> {
    if (!config.FAL_AI_KEY) {
      return { imageUrl: null, error: 'fal.ai API key not configured' };
    }

    try {
      const fullPrompt = this.applyStyle(prompt, style);

      console.log(`Generating FLUX 1.1 Pro image: ${fullPrompt.substring(0, 100)}...`);

      const response = await fetch('https://fal.run/fal-ai/flux-pro/v1.1', {
        method: 'POST',
        headers: {
          'Authorization': `Key ${config.FAL_AI_KEY}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          prompt: fullPrompt,
          image_size: { width, height },
          num_inference_steps: 28,
          guidance_scale: 3.5,
          num_images: 1,
          enable_safety_checker: true,
          output_format: 'jpeg',
          safety_tolerance: '2',
        }),
      });

      if (!response.ok) {
        const errorText = await response.text();
        return { imageUrl: null, error: `FLUX API error ${response.status}: ${errorText}` };
      }

      const result = await response.json() as { images?: Array<{ url: string }> };
      const imageUrl = result.images?.[0]?.url;

      if (imageUrl) {
        console.log(`FLUX image generated: ${imageUrl}`);
        return { imageUrl, error: null };
      }

      return { imageUrl: null, error: 'No image returned from FLUX API' };
    } catch (e) {
      const error = `FLUX generation failed: ${e instanceof Error ? e.message : String(e)}`;
      console.error(error);
      return { imageUrl: null, error };
    }
  }

  /**
   * Generate image using Google Imagen 4 Ultra via fal.ai
   */
  private async generateImagen4(
    prompt: string,
    style: string,
    width: number,
    height: number
  ): Promise<ImageGenerationResult> {
    if (!config.FAL_AI_KEY) {
      return { imageUrl: null, error: 'fal.ai API key not configured' };
    }

    try {
      const fullPrompt = this.applyStyle(prompt, style);

      console.log(`Generating Imagen 4 Ultra image: ${fullPrompt.substring(0, 100)}...`);

      // Determine image size based on dimensions
      let imageSize: string = 'square';
      if (width > height) {
        imageSize = 'landscape_16_9';
      } else if (height > width) {
        imageSize = 'portrait_3_4';
      }

      const response = await fetch('https://fal.run/fal-ai/imagen4/preview/ultra', {
        method: 'POST',
        headers: {
          'Authorization': `Key ${config.FAL_AI_KEY}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          prompt: fullPrompt,
          image_size: imageSize,
          num_images: 1,
          enable_safety_checker: false,
          safety_tolerance: '6',
        }),
      });

      if (!response.ok) {
        const errorText = await response.text();
        return { imageUrl: null, error: `Imagen 4 API error ${response.status}: ${errorText}` };
      }

      const result = await response.json() as { images?: Array<{ url: string }> };
      const imageUrl = result.images?.[0]?.url;

      if (imageUrl) {
        console.log(`Imagen 4 Ultra image generated: ${imageUrl}`);
        return { imageUrl, error: null };
      }

      return { imageUrl: null, error: 'No image returned from Imagen 4 API' };
    } catch (e) {
      const error = `Imagen 4 generation failed: ${e instanceof Error ? e.message : String(e)}`;
      console.error(error);
      return { imageUrl: null, error };
    }
  }

  /**
   * Apply style preset to prompt
   */
  private applyStyle(prompt: string, style: string): string {
    const styleText = STYLE_PRESETS[style] ?? STYLE_PRESETS.cozy_cartoon;
    return `${prompt}, ${styleText}`;
  }

  /**
   * Get current provider
   */
  getProvider(): ImageProvider {
    return this.provider;
  }

  /**
   * Set provider
   */
  setProvider(provider: ImageProvider): void {
    this.provider = provider;
  }
}

// ============================================================
// Default Instance
// ============================================================

export const imageGenerator = new ImageGenerator();
