import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as qenv from '@push.rocks/qenv';
import * as smartai from '../ts/index.js';
import * as path from 'path';
import { promises as fs } from 'fs';

const testQenv = new qenv.Qenv('./', './.nogit/');

let openaiProvider: smartai.OpenAiProvider;

// Helper function to save image results
async function saveImageResult(testName: string, result: any) {
  const sanitizedName = testName.replace(/[^a-z0-9]/gi, '_').toLowerCase();
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
  const filename = `openai_${sanitizedName}_${timestamp}.json`;
  const filepath = path.join('.nogit', 'testresults', 'images', filename);

  await fs.mkdir(path.dirname(filepath), { recursive: true });
  await fs.writeFile(filepath, JSON.stringify(result, null, 2), 'utf-8');

  console.log(`  💾 Saved to: ${filepath}`);

  // Also save the actual image if b64_json is present
  if (result.images && result.images[0]?.b64_json) {
    const imageFilename = `openai_${sanitizedName}_${timestamp}.png`;
    const imageFilepath = path.join('.nogit', 'testresults', 'images', imageFilename);
    await fs.writeFile(imageFilepath, Buffer.from(result.images[0].b64_json, 'base64'));
    console.log(`  🖼️  Image saved to: ${imageFilepath}`);
  }
}

tap.test('OpenAI Image Generation: should initialize provider', async () => {
  const openaiToken = await testQenv.getEnvVarOnDemand('OPENAI_TOKEN');
  expect(openaiToken).toBeTruthy();

  openaiProvider = new smartai.OpenAiProvider({
    openaiToken,
    imageModel: 'gpt-image-1'
  });

  await openaiProvider.start();
  expect(openaiProvider).toBeInstanceOf(smartai.OpenAiProvider);
});

tap.test('OpenAI Image: Basic generation with gpt-image-1', async () => {
  const result = await openaiProvider.imageGenerate({
    prompt: 'A cute robot reading a book in a cozy library, digital art style',
    model: 'gpt-image-1',
    quality: 'medium',
    size: '1024x1024'
  });

  console.log('Basic gpt-image-1 Generation:');
  console.log('- Images generated:', result.images.length);
  console.log('- Model used:', result.metadata?.model);
  console.log('- Quality:', result.metadata?.quality);
  console.log('- Size:', result.metadata?.size);
  console.log('- Tokens used:', result.metadata?.tokensUsed);

  await saveImageResult('basic_generation_gptimage1', result);

  expect(result.images).toBeTruthy();
  expect(result.images.length).toEqual(1);
  expect(result.images[0].b64_json).toBeTruthy();
  expect(result.metadata?.model).toEqual('gpt-image-1');
});

tap.test('OpenAI Image: High quality with transparent background', async () => {
  const result = await openaiProvider.imageGenerate({
    prompt: 'A simple geometric logo of a mountain peak, minimal design, clean lines',
    model: 'gpt-image-1',
    quality: 'high',
    size: '1024x1024',
    background: 'transparent',
    outputFormat: 'png'
  });

  console.log('High Quality Transparent:');
  console.log('- Quality:', result.metadata?.quality);
  console.log('- Background: transparent');
  console.log('- Format:', result.metadata?.outputFormat);
  console.log('- Tokens used:', result.metadata?.tokensUsed);

  await saveImageResult('high_quality_transparent', result);

  expect(result.images.length).toEqual(1);
  expect(result.images[0].b64_json).toBeTruthy();
});

tap.test('OpenAI Image: WebP format with compression', async () => {
  const result = await openaiProvider.imageGenerate({
    prompt: 'A futuristic cityscape at sunset with flying cars, photorealistic',
    model: 'gpt-image-1',
    quality: 'high',
    size: '1536x1024',
    outputFormat: 'webp',
    outputCompression: 85
  });

  console.log('WebP with Compression:');
  console.log('- Format:', result.metadata?.outputFormat);
  console.log('- Compression: 85%');
  console.log('- Size:', result.metadata?.size);

  await saveImageResult('webp_compression', result);

  expect(result.images.length).toEqual(1);
  expect(result.images[0].b64_json).toBeTruthy();
});

tap.test('OpenAI Image: Text rendering with gpt-image-1', async () => {
  const result = await openaiProvider.imageGenerate({
    prompt: 'A vintage cafe sign that says "COFFEE & CODE" in elegant hand-lettered typography, warm colors',
    model: 'gpt-image-1',
    quality: 'high',
    size: '1024x1024'
  });

  console.log('Text Rendering:');
  console.log('- Prompt includes text: "COFFEE & CODE"');
  console.log('- gpt-image-1 has superior text rendering');
  console.log('- Tokens used:', result.metadata?.tokensUsed);

  await saveImageResult('text_rendering', result);

  expect(result.images.length).toEqual(1);
  expect(result.images[0].b64_json).toBeTruthy();
});

tap.test('OpenAI Image: Multiple images generation', async () => {
  const result = await openaiProvider.imageGenerate({
    prompt: 'Abstract colorful geometric patterns, modern minimalist art',
    model: 'gpt-image-1',
    n: 2,
    quality: 'medium',
    size: '1024x1024'
  });

  console.log('Multiple Images:');
  console.log('- Images requested: 2');
  console.log('- Images generated:', result.images.length);

  await saveImageResult('multiple_images', result);

  expect(result.images.length).toEqual(2);
  expect(result.images[0].b64_json).toBeTruthy();
  expect(result.images[1].b64_json).toBeTruthy();
});

tap.test('OpenAI Image: Low moderation setting', async () => {
  const result = await openaiProvider.imageGenerate({
    prompt: 'A fantasy battle scene with warriors and dragons',
    model: 'gpt-image-1',
    moderation: 'low',
    quality: 'medium'
  });

  console.log('Low Moderation:');
  console.log('- Moderation: low (less restrictive filtering)');
  console.log('- Tokens used:', result.metadata?.tokensUsed);

  await saveImageResult('low_moderation', result);

  expect(result.images.length).toEqual(1);
  expect(result.images[0].b64_json).toBeTruthy();
});

tap.test('OpenAI Image Editing: edit with gpt-image-1', async () => {
  // First, generate a base image
  const baseResult = await openaiProvider.imageGenerate({
    prompt: 'A simple white cat sitting on a red cushion',
    model: 'gpt-image-1',
    quality: 'low',
    size: '1024x1024'
  });

  const baseImageBuffer = Buffer.from(baseResult.images[0].b64_json!, 'base64');

  // Now edit it
  const editResult = await openaiProvider.imageEdit({
    image: baseImageBuffer,
    prompt: 'Change the cat to orange and add stylish sunglasses',
    model: 'gpt-image-1',
    quality: 'medium'
  });

  console.log('Image Editing:');
  console.log('- Base image created');
  console.log('- Edit: change color and add sunglasses');
  console.log('- Result images:', editResult.images.length);

  await saveImageResult('image_edit', editResult);

  expect(editResult.images.length).toEqual(1);
  expect(editResult.images[0].b64_json).toBeTruthy();
});

tap.test('OpenAI Image: should clean up provider', async () => {
  await openaiProvider.stop();
  console.log('OpenAI image provider stopped successfully');
});

export default tap.start();
