"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = imageRoutes;
const path_1 = require("path");
const file_ops_js_1 = require("../modules/data-store/file-ops.js");
const prompt_safety_js_1 = require("../modules/image-engine/prompt-safety.js");
async function imageRoutes(app, opts) {
    const imageEngine = opts.imageEngine;
    if (!imageEngine)
        throw new Error('imageEngine is required');
    const dataStore = opts.dataStore ?? (await import('../modules/data-store/index.js')).dataStore;
    // POST /characters/:id/images/generate — Generate image with custom prompt + reference images
    app.post('/characters/:id/images/generate', async (request, reply) => {
        const { id } = request.params;
        const body = request.body;
        try {
            const character = await dataStore.getCharacter(id);
            if (!character) {
                return reply.status(404).send({ success: false, error: 'Character not found' });
            }
            if (!body.prompt || !body.prompt.trim()) {
                return reply.status(400).send({ success: false, error: 'prompt is required' });
            }
            // Load master prompt for negative prompt
            const { readJSON: readJSONFn } = await import('../modules/data-store/file-ops.js');
            const { resolve: resolvePath } = await import('path');
            const { config: appConfig } = await import('../utils/config.js');
            const masterPromptPath = resolvePath(appConfig.dataDir, 'characters', id, 'master-prompt.json');
            const masterPrompt = await readJSONFn(masterPromptPath);
            const negativePrompt = masterPrompt?.negative_prompt || 'deformed, blurry, bad anatomy, low quality';
            // Load 7 reference image URLs
            const refUrlsPath = resolvePath(appConfig.dataDir, 'characters', id, 'reference-urls.json');
            const refUrls = await readJSONFn(refUrlsPath);
            const referenceImageUrls = refUrls ? Object.values(refUrls).filter(Boolean) : [];
            // Sanitize prompt
            const safetyResult = (0, prompt_safety_js_1.sanitizePrompt)(body.prompt.trim());
            const finalPrompt = safetyResult.sanitizedPrompt;
            // Generate via image provider (KIE → Gemini fallback)
            const { getImageProvider } = await import('../modules/image-engine/image-provider.js');
            const provider = getImageProvider();
            const genResult = await provider.generateAndWait({
                model: 'nano-banana-2',
                prompt: finalPrompt,
                negativePrompt,
                aspectRatio: body.aspectRatio || '9:16',
                imageInput: referenceImageUrls.length > 0 ? referenceImageUrls : undefined,
            });
            const imageUrl = genResult.imageUrl;
            // Download and save to disk
            const { fetch: fetchFn } = await import('undici');
            const { writeFile: writeFileFn } = await import('fs/promises');
            const { ensureDir: ensureDirFn } = await import('../modules/data-store/file-ops.js');
            const imgResponse = await fetchFn(imageUrl);
            if (!imgResponse.ok)
                throw new Error('Failed to download generated image');
            const buffer = Buffer.from(await imgResponse.arrayBuffer());
            const imageId = `photo_${Date.now()}`;
            const imagesDir = dataStore.getGeneratedImagesDir(id);
            await ensureDirFn(imagesDir);
            const savePath = resolvePath(imagesDir, `${imageId}.jpg`);
            await writeFileFn(savePath, buffer);
            return reply.status(201).send({
                success: true,
                data: {
                    imageId,
                    characterId: id,
                    prompt: finalPrompt,
                    imageUrl: `/static/characters/${id}/generated-images/${imageId}.jpg`,
                    remoteUrl: imageUrl,
                    provider: genResult.provider,
                    referenceImagesUsed: referenceImageUrls.length,
                    safetyModified: safetyResult.wasModified,
                },
            });
        }
        catch (err) {
            return reply.status(500).send({ success: false, error: err.message });
        }
    });
    // GET /characters/:id/images — List generated images
    app.get('/characters/:id/images', async (request, reply) => {
        const { id } = request.params;
        try {
            const character = await dataStore.getCharacter(id);
            if (!character) {
                return reply.status(404).send({ success: false, error: 'Character not found' });
            }
            const imagesDir = dataStore.getGeneratedImagesDir(id);
            const files = await (0, file_ops_js_1.listFiles)(imagesDir, '.jpg');
            const images = files.map((file) => ({
                imageId: file.replace('.jpg', ''),
                filename: file,
                url: `/static/characters/${id}/generated-images/${file}`,
                createdAt: file.replace('photo_', '').replace('.jpg', ''),
            })).sort((a, b) => b.imageId.localeCompare(a.imageId));
            return reply.status(200).send({ success: true, data: images });
        }
        catch (err) {
            return reply.status(500).send({ success: false, error: err.message });
        }
    });
    // GET /characters/:id/images/:imageId — Get image detail and quality report
    app.get('/characters/:id/images/:imageId', async (request, reply) => {
        const { id, imageId } = request.params;
        try {
            const character = await dataStore.getCharacter(id);
            if (!character) {
                return reply.status(404).send({ success: false, error: 'Character not found' });
            }
            const imagesDir = dataStore.getGeneratedImagesDir(id);
            const imagePath = (0, path_1.resolve)(imagesDir, `${imageId}.jpg`);
            if (!(0, file_ops_js_1.fileExists)(imagePath)) {
                return reply.status(404).send({ success: false, error: 'Image not found' });
            }
            const reportsDir = dataStore.getQualityReportsDir(id);
            const qualityReport = await (0, file_ops_js_1.readJSON)((0, path_1.resolve)(reportsDir, `${imageId}.json`));
            return reply.status(200).send({
                success: true,
                data: {
                    imageId,
                    characterId: id,
                    filename: `${imageId}.jpg`,
                    qualityReport: qualityReport ?? null,
                },
            });
        }
        catch (err) {
            return reply.status(500).send({ success: false, error: err.message });
        }
    });
    // DELETE /characters/:id/images/:imageId — Delete image
    app.delete('/characters/:id/images/:imageId', async (request, reply) => {
        const { id, imageId } = request.params;
        try {
            const character = await dataStore.getCharacter(id);
            if (!character) {
                return reply.status(404).send({ success: false, error: 'Character not found' });
            }
            const imagesDir = dataStore.getGeneratedImagesDir(id);
            const imagePath = (0, path_1.resolve)(imagesDir, `${imageId}.jpg`);
            if (!(0, file_ops_js_1.fileExists)(imagePath)) {
                return reply.status(404).send({ success: false, error: 'Image not found' });
            }
            const deleted = await (0, file_ops_js_1.deleteFile)(imagePath);
            // Also delete quality report if it exists
            const reportsDir = dataStore.getQualityReportsDir(id);
            await (0, file_ops_js_1.deleteFile)((0, path_1.resolve)(reportsDir, `${imageId}.json`));
            return reply.status(200).send({
                success: true,
                data: { imageId, deleted },
            });
        }
        catch (err) {
            return reply.status(500).send({ success: false, error: err.message });
        }
    });
    // POST /images/prompt-safety-check — Check if a prompt is policy-safe
    app.post('/images/prompt-safety-check', async (request, reply) => {
        const { prompt } = request.body;
        if (!prompt) {
            return reply.status(400).send({ success: false, error: 'prompt is required' });
        }
        const check = (0, prompt_safety_js_1.checkPromptSafety)(prompt);
        const sanitized = (0, prompt_safety_js_1.sanitizePrompt)(prompt);
        return reply.status(200).send({
            success: true,
            data: {
                safe: check.safe,
                issues: check.issues,
                sanitizedPrompt: sanitized.sanitizedPrompt,
                changes: sanitized.changes,
                warnings: sanitized.warnings,
                wasModified: sanitized.wasModified,
            },
        });
    });
    // GET /images/safe-outfit-options — Get policy-safe outfit suggestions
    app.get('/images/safe-outfit-options', async (_request, reply) => {
        return reply.status(200).send({
            success: true,
            data: prompt_safety_js_1.SAFE_OUTFIT_OPTIONS,
        });
    });
    // POST /characters/:id/images/ai-generate — Generate image with AI-created prompt
    app.post('/characters/:id/images/ai-generate', async (request, reply) => {
        const { id } = request.params;
        const body = request.body;
        try {
            const character = await dataStore.getCharacter(id);
            if (!character) {
                return reply.status(404).send({ success: false, error: 'Character not found' });
            }
            const { generateImagePrompt } = await import('../modules/image-engine/ai-prompt-generator.js');
            const generated = await generateImagePrompt(character, {
                category: body?.category,
                context: body?.context,
                mood: body?.mood,
            });
            // Load reference image URLs
            const { config: appConfig } = await import('../utils/config.js');
            const refUrlsPath = (0, path_1.resolve)(appConfig.dataDir, 'characters', id, 'reference-urls.json');
            const refUrls = await (0, file_ops_js_1.readJSON)(refUrlsPath);
            const referenceImageUrls = refUrls ? Object.values(refUrls).filter(Boolean) : [];
            // Generate via image provider (KIE → Gemini fallback)
            const { getImageProvider } = await import('../modules/image-engine/image-provider.js');
            const provider = getImageProvider();
            const genResult = await provider.generateAndWait({
                model: 'nano-banana-2',
                prompt: generated.prompt,
                negativePrompt: generated.negativePrompt,
                aspectRatio: generated.aspectRatio,
                imageInput: referenceImageUrls.length > 0 ? referenceImageUrls : undefined,
            });
            const imageUrl = genResult.imageUrl;
            // Download and save
            const { fetch: fetchFn } = await import('undici');
            const { writeFile: writeFileFn } = await import('fs/promises');
            const { ensureDir: ensureDirFn } = await import('../modules/data-store/file-ops.js');
            const imgResponse = await fetchFn(imageUrl);
            if (!imgResponse.ok)
                throw new Error('Failed to download generated image');
            const buffer = Buffer.from(await imgResponse.arrayBuffer());
            const imageId = `photo_${Date.now()}`;
            const imagesDir = dataStore.getGeneratedImagesDir(id);
            await ensureDirFn(imagesDir);
            const savePath = (0, path_1.resolve)(imagesDir, `${imageId}.jpg`);
            await writeFileFn(savePath, buffer);
            return reply.status(201).send({
                success: true,
                data: {
                    imageId,
                    characterId: id,
                    prompt: generated.prompt,
                    category: generated.category,
                    imageUrl: `/static/characters/${id}/generated-images/${imageId}.jpg`,
                    remoteUrl: imageUrl,
                    provider: genResult.provider,
                    referenceImagesUsed: referenceImageUrls.length,
                    safetyModified: generated.safetyModified,
                },
            });
        }
        catch (err) {
            return reply.status(500).send({ success: false, error: err.message });
        }
    });
    // POST /characters/:id/images/multi-model-test — Test same prompt across multiple models (NO NSFW sanitization)
    app.post('/characters/:id/images/multi-model-test', async (request, reply) => {
        const { id } = request.params;
        const body = request.body;
        try {
            const character = await dataStore.getCharacter(id);
            if (!character) {
                return reply.status(404).send({ success: false, error: 'Character not found' });
            }
            // Load reference image URLs
            const { config: appConfig } = await import('../utils/config.js');
            const refUrlsPath = (0, path_1.resolve)(appConfig.dataDir, 'characters', id, 'reference-urls.json');
            const refUrls = await (0, file_ops_js_1.readJSON)(refUrlsPath);
            const referenceImageUrls = refUrls ? Object.values(refUrls).filter(Boolean) : [];
            // Build prompt from character master-prompt if not provided
            let prompt = body?.prompt?.trim();
            if (!prompt) {
                const masterPromptPath = (0, path_1.resolve)(appConfig.dataDir, 'characters', id, 'master-prompt.json');
                const masterPrompt = await (0, file_ops_js_1.readJSON)(masterPromptPath);
                prompt = `${masterPrompt?.subject || ''}, ${masterPrompt?.clothing || ''}, confident pose, golden hour lighting, shot on iPhone 15 Pro, instagram style`;
            }
            // Optionally sanitize
            const skipSanitization = body?.skipSanitization ?? true; // default: skip for testing
            let finalPrompt = prompt;
            if (!skipSanitization) {
                const safety = (0, prompt_safety_js_1.sanitizePrompt)(prompt);
                finalPrompt = safety.sanitizedPrompt;
            }
            const models = (body?.models || ['seedream5-0-lite', 'seedream-4-5', 'flux-2']);
            const aspectRatio = (body?.aspectRatio || '9:16');
            const { createKIEClient } = await import('../modules/image-engine/kie-client.js');
            const { getImageProvider } = await import('../modules/image-engine/image-provider.js');
            const imgProvider = getImageProvider();
            const kieClient = imgProvider.getKIEClient();
            const { fetch: fetchFn } = await import('undici');
            const { writeFile: writeFileFn } = await import('fs/promises');
            const { ensureDir: ensureDirFn } = await import('../modules/data-store/file-ops.js');
            const results = [];
            // Generate with each model in parallel
            const tasks = models.map(async (model) => {
                const startTime = Date.now();
                try {
                    // Build model-specific request
                    const req = {
                        model,
                        prompt: finalPrompt,
                        aspectRatio,
                    };
                    // nano-banana-2 uses imageInput, others use referenceImages
                    if (model === 'nano-banana-2') {
                        req.imageInput = referenceImageUrls.length > 0 ? referenceImageUrls : undefined;
                        req.resolution = '1K';
                        req.outputFormat = 'jpg';
                    }
                    else {
                        req.referenceImages = referenceImageUrls.length > 0 ? referenceImageUrls : undefined;
                    }
                    // Use unified provider for fallback support
                    const genResult = await imgProvider.generateAndWait(req);
                    const imageUrl = genResult.imageUrl;
                    const elapsed = Date.now() - startTime;
                    // Download and save
                    const imgResponse = await fetchFn(imageUrl);
                    if (!imgResponse.ok)
                        throw new Error('Failed to download');
                    const buffer = Buffer.from(await imgResponse.arrayBuffer());
                    const imageId = `test_${model.replace(/[^a-z0-9]/g, '_')}_${Date.now()}`;
                    const imagesDir = dataStore.getGeneratedImagesDir(id);
                    await ensureDirFn(imagesDir);
                    const savePath = (0, path_1.resolve)(imagesDir, `${imageId}.jpg`);
                    await writeFileFn(savePath, buffer);
                    return {
                        model,
                        success: true,
                        imageId,
                        imageUrl: `/static/characters/${id}/generated-images/${imageId}.jpg`,
                        remoteUrl: imageUrl,
                        elapsedMs: elapsed,
                    };
                }
                catch (err) {
                    return {
                        model,
                        success: false,
                        error: err.message,
                        elapsedMs: Date.now() - startTime,
                    };
                }
            });
            const settled = await Promise.all(tasks);
            return reply.status(200).send({
                success: true,
                data: {
                    characterId: id,
                    prompt: finalPrompt,
                    sanitized: !skipSanitization,
                    referenceImagesUsed: referenceImageUrls.length,
                    results: settled,
                },
            });
        }
        catch (err) {
            return reply.status(500).send({ success: false, error: err.message });
        }
    });
}
//# sourceMappingURL=images.js.map