/**
 * Image Generation plugin for OpenWriter.
 * Right-click an empty paragraph → "Generate image" → AI creates an image inline.
 * Uses Google Gemini (Nano Banana 2) for generation, saves to /_images/.
 */
import { join } from 'path';
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
import { randomUUID } from 'crypto';
import { homedir } from 'os';
/** Fallback: generate image via the publish platform API, download and save locally */
async function generateViaPlatform(prompt, dataDir, imageApiKey, aspectRatio = '16:9') {
    const configPath = join(homedir(), '.openwriter', 'config.json');
    if (!existsSync(configPath))
        return null;
    const config = JSON.parse(readFileSync(configPath, 'utf8'));
    const publishConfig = config.plugins?.['@openwriter/plugin-publish']?.config || {};
    const platformKey = publishConfig['api-key'];
    const apiUrl = publishConfig['api-url'] || 'https://publish.openwriter.io';
    const profile = config.activeProfile || 'Default';
    if (!platformKey)
        return null;
    console.log(`[ImageGen] Generating image (platform): "${prompt.slice(0, 80)}..."`);
    const res = await fetch(`${apiUrl}/images/generate`, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${platformKey}`,
            'X-Profile': profile,
            // BYO image key → worker skips the shared-key allotment and bills the user's own key (uncapped).
            ...(imageApiKey ? { 'X-Image-Key': imageApiKey } : {}),
        },
        body: JSON.stringify({ prompt, aspect_ratio: aspectRatio }),
    });
    if (!res.ok) {
        const err = await res.json().catch(() => ({ error: `HTTP ${res.status}` }));
        throw new Error(err.error || 'Platform image generation failed');
    }
    const data = await res.json();
    // Download image and save locally
    const imageRes = await fetch(data.url);
    const imageBuffer = Buffer.from(await imageRes.arrayBuffer());
    const imagesDir = join(dataDir, '_images');
    if (!existsSync(imagesDir))
        mkdirSync(imagesDir, { recursive: true });
    const filename = `${randomUUID().slice(0, 8)}.png`;
    writeFileSync(join(imagesDir, filename), imageBuffer);
    console.log(`[ImageGen] Saved (platform): ${join(imagesDir, filename)}`);
    return { success: true, src: `/_images/${filename}` };
}
const plugin = {
    name: '@openwriter/plugin-image-gen',
    version: '0.1.0',
    description: 'Generate images with AI — right-click empty paragraphs',
    category: 'image-generation',
    configSchema: {
        'gemini-api-key': {
            type: 'string',
            env: 'GEMINI_API_KEY',
            required: false,
            description: 'Google Gemini API key for image generation (optional — falls back to publish platform)',
        },
        imageApiKey: {
            type: 'string',
            required: false,
            description: "Your own image API key (Gemini) — unlimited generations at your cost. Leave blank to use OpenWriter's included allotment.",
        },
    },
    registerRoutes(ctx) {
        ctx.app.post('/api/image-gen/generate', async (req, res) => {
            try {
                const { prompt } = req.body;
                if (!prompt || typeof prompt !== 'string') {
                    res.status(400).json({ success: false, error: 'prompt is required' });
                    return;
                }
                if (prompt.length > 1000) {
                    res.status(400).json({ success: false, error: 'prompt must be under 1000 characters' });
                    return;
                }
                const apiKey = ctx.config['gemini-api-key'] || process.env.GEMINI_API_KEY || '';
                let imageBytes;
                if (apiKey) {
                    // Local Gemini generation
                    const { GoogleGenAI } = await import('@google/genai');
                    const ai = new GoogleGenAI({ apiKey });
                    console.log(`[ImageGen] Generating image (local): "${prompt.slice(0, 80)}..."`);
                    const response = await ai.models.generateContent({
                        model: 'gemini-3.1-flash-image-preview',
                        contents: `Generate a 16:9 aspect ratio image: ${prompt}`,
                        config: {
                            responseModalities: ['IMAGE'],
                        },
                    });
                    const parts = response.candidates?.[0]?.content?.parts;
                    if (!parts || parts.length === 0) {
                        res.status(422).json({ success: false, error: 'No image generated — content may have been filtered' });
                        return;
                    }
                    const imagePart = parts.find((p) => p.inlineData);
                    imageBytes = imagePart?.inlineData?.data;
                    if (!imageBytes) {
                        res.status(422).json({ success: false, error: 'No image data in response' });
                        return;
                    }
                }
                else {
                    // Fallback: generate via publish platform API.
                    // Pass the user's own image key (if set) so the worker bills it instead of the shared allotment.
                    const platformResult = await generateViaPlatform(prompt, ctx.dataDir, ctx.config['imageApiKey']);
                    if (!platformResult) {
                        res.status(400).json({ success: false, error: 'No GEMINI_API_KEY and publish platform not configured. Set GEMINI_API_KEY or log in to the publish plugin.' });
                        return;
                    }
                    // platformResult already saved to disk
                    res.json(platformResult);
                    return;
                }
                // Save to dataDir/_images/
                const imagesDir = join(ctx.dataDir, '_images');
                if (!existsSync(imagesDir))
                    mkdirSync(imagesDir, { recursive: true });
                const filename = `${randomUUID().slice(0, 8)}.png`;
                const filepath = join(imagesDir, filename);
                writeFileSync(filepath, Buffer.from(imageBytes, 'base64'));
                console.log(`[ImageGen] Saved: ${filepath}`);
                res.json({ success: true, src: `/_images/${filename}` });
            }
            catch (err) {
                const msg = err?.message || 'Image generation failed';
                console.error('[ImageGen] Generation failed:', msg);
                const friendly = /Unexpected token.*<!DOCTYPE/i.test(msg)
                    ? 'Image generation failed — your Gemini API key may be invalid or expired. Check your GEMINI_API_KEY.'
                    : msg;
                res.status(500).json({ success: false, error: friendly });
            }
        });
    },
    contextMenuItems() {
        return [
            {
                label: 'Generate image',
                action: 'img:generate',
                condition: 'always',
                promptForInput: true,
            },
        ];
    },
};
export default plugin;
