import * as fs from 'fs/promises';
import * as path from 'path';
import axios from 'axios';
import dotenv from 'dotenv';

dotenv.config();

interface ImageSize {
    width: number;
    height: number;
}

async function generateImage(
    prompt: string,
    newFileName: string,
    comfyBaseUrl: string,
    comfyOutputDir: string,
    imageModel: 'qwen' | 'flux' = 'qwen',
    size: ImageSize = { width: 720, height: 1280 }
): Promise<string> {
    const COMFY_BASE_URL = comfyBaseUrl.replace(/\/$/, '');
    const COMFY_OUTPUT_DIR = comfyOutputDir;
    let workflow;
    if (imageModel === 'qwen') {
        workflow = JSON.parse(await fs.readFile('src/comfyworkflows/generate_image.json', 'utf-8'));
        workflow['6']['inputs']['text'] = prompt;
        workflow['72']['inputs']['width'] = size.width;
        workflow['72']['inputs']['height'] = size.height;
    } else if (imageModel === 'flux') {
        workflow = JSON.parse(await fs.readFile('src/comfyworkflows/generate_image_flux.json', 'utf-8'));
        workflow['41']['inputs']['clip_l'] = prompt;
        workflow['41']['inputs']['t5xxl'] = prompt;
        workflow['27']['inputs']['width'] = size.width;
        workflow['27']['inputs']['height'] = size.height;
    } else {
        throw new Error(`Unsupported image model: ${imageModel}`);
    }

    const response = await axios.post(`${COMFY_BASE_URL}/prompt`, { prompt: workflow });
    const promptId = response.data.prompt_id;

    let history;
    do {
        await new Promise(resolve => setTimeout(resolve, 1000));
        const historyResponse = await axios.get(`${COMFY_BASE_URL}/history/${promptId}`);
        history = historyResponse.data[promptId];
    } while (!history || Object.keys(history.outputs).length === 0);

    const files = await fs.readdir(COMFY_OUTPUT_DIR!);
    const generatedFiles = files.filter(file => file.startsWith('RADOMVIDEOMAKERIMG'));

    const fileStats = await Promise.all(
        generatedFiles.map(async (file) => {
            const stat = await fs.stat(path.join(COMFY_OUTPUT_DIR!, file));
            return { file, mtime: stat.mtime };
        })
    );

    fileStats.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());

    const latestFile = fileStats[0].file;
    const newFilePath = path.resolve('./generated', newFileName);

    await fs.mkdir('./generated', { recursive: true });
    
    const sourcePath = path.join(COMFY_OUTPUT_DIR!, latestFile);
    await fs.copyFile(sourcePath, newFilePath);
    //await fs.unlink(sourcePath);

    return newFilePath;
}

export { generateImage };
