import { DefaultService, PromptOptimizationRequest } from '@lib/api';
import { GenerationStatus, VideoGenerationRequest } from '@/types';
import { toast } from 'sonner';
import {
    validateImageGenerationParams,
    validateVideoGenerationParams,
    ValidationError
} from '@lib/utils/generationValidation';
import { StyleProcessor } from '@lib/utils/styleProcessor';

// Shared Helper for Polling
const wait = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

export interface GenerationResult {
    status: GenerationStatus | 'cancelled';
    urls?: string[];
    error?: string;
}

export class GenerationService {
    /**
     * Polls a task until it succeeds, fails, or times out.
     */
    static async pollTask(
        taskId: string,
        type: 'image' | 'video' | 'audio' | 'music',
        model?: string,
        maxAttempts = 60,
        interval = 5000,
    ): Promise<GenerationResult> {
        let attempts = 0;
        while (attempts < maxAttempts) {
            try {
                const response = await DefaultService.getTaskStatus(taskId);
                const statusRes = (response as any).data;
                
                if (!statusRes) {
                     // If response is valid but data is empty, maybe task not found?
                     if (response.code !== '2000' && response.code !== undefined) {
                         return { status: 'failed', error: response.message || 'API Error' };
                     }
                     throw new Error("No data returned");
                }
                
                // Normalize status
                const status = (statusRes.status || 'unknown').toLowerCase();

                if (status === 'succeeded' || status === 'success') {
                    let urls: string[] = [];
                    if (statusRes.result && statusRes.result.urls) {
                        urls = statusRes.result.urls;
                    }
                    return { status: 'success', urls };
                } else if (status === 'failed') {
                     return { status: 'failed', error: statusRes.error || 'Task failed' };
                } else if (status === 'cancelled' || status === 'canceled') {
                     return { status: 'cancelled', error: 'Task cancelled' };
                } else if (statusRes.error && status !== 'pending' && status !== 'processing' && status !== 'queued' && status !== 'running') {
                     // Fallback if error is present but status isn't explicitly failed
                     return { status: 'failed', error: statusRes.error };
                }
                
                // Continue polling
                await wait(interval);
                attempts++;
            } catch (error: any) {
                console.warn("Polling error:", error);
                // Don't fail immediately on network glitch
                await wait(interval);
                attempts++;
            }
        }
        return { status: 'failed', error: 'Generation timed out' };
    }
}

export interface ImageGenerationPayload {
    taskId: string | undefined;
    result: Promise<GenerationResult>;
}

export class ImageGenerationService {
    static async generate(params: {
        prompt: string;
        model: string;
        negativePrompt?: string;
        aspectRatio?: string;
        resolution?: string;
        n?: number;
        styleId?: string;  // 改为 styleId，不再使用 stylePreset
        imageInputs?: string[];
        loraStrength?: number;
        projectId?: string;
        source?: string;
        sourceId?: string;
        onDebugPayload?: (payload: {
            prompt: string;
            model: string;
            styleId?: string;
            extraParams?: Record<string, any>;
        }) => void;
    }): Promise<ImageGenerationPayload> {
        const debugGenerationPayload = process.env.NEXT_PUBLIC_DEBUG_GENERATION_PAYLOAD === '1';
        // 应用风格（在验证之前）
        let finalPrompt = params.prompt;
        let extraParams: Record<string, any> = {};
        
        if (params.styleId) {
            try {
                const styled = await StyleProcessor.applyStyle(
                    params.prompt, 
                    params.styleId,
                    { loraStrength: params.loraStrength }
                );
                finalPrompt = styled.prompt;
                if (styled.extraParams) {
                    extraParams = styled.extraParams;
                }
                
                console.log('[ImageGenerationService] Style applied:', {
                    styleId: params.styleId,
                    originalPrompt: params.prompt.substring(0, 50) + '...',
                    styledPrompt: finalPrompt.substring(0, 50) + '...',
                    extraParams
                });
            } catch (error) {
                console.error('[ImageGenerationService] Failed to apply style:', error);
                // 继续使用原始 prompt
            }
        }
        
        // 如果没有应用风格，但用户设置了 loraStrength，则手动添加
        if (params.loraStrength !== undefined && !extraParams.lora_strength) {
            extraParams.lora_strength = params.loraStrength;
        }
        
        // 前端参数验证
        try {
            validateImageGenerationParams({
                prompt: finalPrompt,
                model: params.model,
                negativePrompt: params.negativePrompt,
                aspectRatio: params.aspectRatio,
                resolution: params.resolution,
                n: params.n
            });
        } catch (error) {
            if (error instanceof ValidationError) {
                console.error(`[ImageGenerationService] Validation error in ${error.field}:`, error.message);
                return {
                    taskId: undefined,
                    result: Promise.resolve({ 
                        status: 'failed', 
                        error: `Validation error: ${error.message}` 
                    })
                };
            }
            throw error;
        }

        // 构建 payload
        const payload = {
            prompt: finalPrompt,  // 使用应用风格后的 prompt
            negativePrompt: params.negativePrompt,
            model: params.model,
            aspectRatio: params.aspectRatio,
            resolution: params.resolution,
            n: params.n,
            projectId: params.projectId,
            imageInputs: params.imageInputs,
            source: params.source,
            sourceId: params.sourceId,
            extraParams  // 包含所有 LoRA 参数
        };

        if (params.onDebugPayload) {
            params.onDebugPayload({
                prompt: payload.prompt,
                model: payload.model,
                styleId: params.styleId,
                extraParams: payload.extraParams,
            });
        }

        if (debugGenerationPayload && typeof window !== 'undefined') {
            const summary = [
                `styleId: ${params.styleId || 'none'}`,
                `model: ${payload.model}`,
                `prompt: ${payload.prompt.slice(0, 180)}${payload.prompt.length > 180 ? '...' : ''}`,
            ].join('\n');
            toast.message('Image Payload Debug', { description: summary, duration: 8000 });
            console.log('[ImageGenerationService][DebugPayload]', {
                styleId: params.styleId,
                model: payload.model,
                prompt: payload.prompt,
                extraParams: payload.extraParams,
            });
        }

        try {
            console.log('[ImageGenerationService] Payload:', {
                ...payload,
                imageInputs: payload.imageInputs?.map(url => url.substring(0, 100) + '...'),
                prompt: payload.prompt.substring(0, 100) + '...'
            });

            const response = await DefaultService.generateImage(payload);
            const res = (response as any).data;

            if (res && res.task_id) {
                const taskId = res.task_id;
                const resultPromise = GenerationService.pollTask(taskId, 'image', params.model);
                return { taskId, result: resultPromise };
            }
            return {
                taskId: undefined,
                result: Promise.resolve({ status: 'failed', error: (response as any).message || 'No Task ID returned' })
            };
        } catch (e: any) {
            console.error("Image Gen Error:", e);
            return {
                taskId: undefined,
                result: Promise.resolve({ status: 'failed', error: e.message || 'Unknown error' })
            };
        }
    }

    static async optimizePrompt(prompt: string, template?: string): Promise<string> {
        try {
            const response = await DefaultService.optimizePromptEndpoint({
                prompt,
                target_type: PromptOptimizationRequest.target_type.IMAGE,
                template
            });
            const res = (response as any).data;
            return res.optimized_prompt || prompt;
        } catch (error) {
            console.error("Failed to optimize prompt:", error);
            return prompt;
        }
    }
}

export interface VideoGenerationPayload {
    taskId: string | undefined;
    result: Promise<GenerationResult>;
}

export class VideoGenerationService {
    static async generate(params: {
        prompt: string;
        model: string;
        aspectRatio?: string;
        resolution?: string;
        n?: number;
        duration?: number;
        cameraControl?: string;
        imageInputs?: string[];
        videoInputs?: string[];
        audioInputs?: string[];
        projectId?: string;
        negativePrompt?: string;
        shotType?: string;
        enableAudio?: boolean;
        styleId?: string;  // 添加 styleId 支持
        source?: string;
        sourceId?: string;
    }): Promise<VideoGenerationPayload> {
        // 应用风格（在验证之前）
        let finalPrompt = params.prompt;
        let extraParams: Record<string, any> = {};
        
        if (params.styleId) {
            try {
                const styled = await StyleProcessor.applyStyle(
                    params.prompt, 
                    params.styleId
                );
                finalPrompt = styled.prompt;
                if (styled.extraParams) {
                    extraParams = styled.extraParams;
                }
                
                console.log('[VideoGenerationService] Style applied:', {
                    styleId: params.styleId,
                    originalPrompt: params.prompt.substring(0, 50) + '...',
                    styledPrompt: finalPrompt.substring(0, 50) + '...'
                });
            } catch (error) {
                console.error('[VideoGenerationService] Failed to apply style:', error);
                // 继续使用原始 prompt
            }
        }
        
        // 前端参数验证
        try {
            validateVideoGenerationParams({
                prompt: finalPrompt,
                model: params.model,
                negativePrompt: params.negativePrompt,
                aspectRatio: params.aspectRatio,
                resolution: params.resolution,
                n: params.n,
                duration: params.duration
            });
        } catch (error) {
            if (error instanceof ValidationError) {
                console.error(`[VideoGenerationService] Validation error in ${error.field}:`, error.message);
                return {
                    taskId: undefined,
                    result: Promise.resolve({ 
                        status: 'failed', 
                        error: `Validation error: ${error.message}` 
                    })
                };
            }
            throw error;
        }

        try {
            // 构建 payload，不设置默认值（让后端处理）
            const payload: VideoGenerationRequest = {
                prompt: finalPrompt,  // 使用应用风格后的 prompt
                model: params.model,
                duration: params.duration, // 不设置默认值
                aspectRatio: params.aspectRatio,
                resolution: params.resolution,
                negativePrompt: params.negativePrompt,
                shotType: params.shotType,
                enableAudio: params.enableAudio, // 不设置默认值
                cameraControl: params.cameraControl,
                imageInputs: params.imageInputs,
                videoInputs: params.videoInputs,
                audioInputs: params.audioInputs,
                projectId: params.projectId,
                n: params.n,
                source: params.source,
                sourceId: params.sourceId,
                extraParams  // 包含风格相关参数
            };

            const response = await DefaultService.generateVideo(payload);
            const res = (response as any).data;

            if (res && res.task_id) {
                const taskId = res.task_id;
                const resultPromise = GenerationService.pollTask(taskId, 'video', params.model, 120);
                return { taskId, result: resultPromise };
            }
            return {
                taskId: undefined,
                result: Promise.resolve({ status: 'failed', error: (response as any).message || 'No Task ID returned' })
            };
        } catch (e: any) {
            console.error("Video Gen Error:", e);
            return {
                taskId: undefined,
                result: Promise.resolve({ status: 'failed', error: e.message || 'Unknown error' })
            };
        }
    }

    static async optimizePrompt(prompt: string, template?: string): Promise<string> {
        try {
            const response = await DefaultService.optimizePromptEndpoint({
                prompt,
                target_type: PromptOptimizationRequest.target_type.VIDEO,
                template
            });
            const res = (response as any).data;
            return res.optimized_prompt || prompt;
        } catch (error) {
            console.error("Failed to optimize prompt:", error);
            return prompt;
        }
    }
}

export class AudioGenerationService {
    static async generate(params: {
        text: string;
        model: string;
        voice?: string;
        storyboardId?: string;
        projectId?: string;
        referenceAudio?: string;
        persona?: any;
        emotion?: any;
        /** 创建任务后立即回调，与图片/视频/音乐一致，便于写入节点与刷新后恢复轮询 */
        onTaskId?: (taskId: string) => void;
    }): Promise<GenerationResult> {
        try {
            const {
                text,
                voice = 'alloy',
                storyboardId = 'temp',
                projectId = 'temp',
                model,
                persona,
                emotion,
                referenceAudio,
            } = params;

            const payload = {
                text,
                model,
                voice,
                storyboardId,
                projectId,
                extraParams: {
                    persona,
                    emotion,
                    reference_audio: referenceAudio
                }
            };

            const response = await DefaultService.generateAudioUnified(payload);
            const res = (response as any).data;

            if (res && res.audio_url) {
                return { status: 'success', urls: [res.audio_url] };
            }
            if (res && res.task_id) {
                params.onTaskId?.(res.task_id);
                return await GenerationService.pollTask(res.task_id, 'audio', model);
            }

            return { status: 'failed', error: response.message || 'No audio URL returned' };
        } catch (e: any) {
            console.error("Audio Gen Error:", e);
            return { status: 'failed', error: e.message || 'Unknown error' };
        }
    }

    static async transcribe(audioData: string): Promise<string> {
        // TODO: Connect to backend transcription service
        console.warn("Transcription service currently disabled during backend migration");
        return "Transcription unavailable.";
    }
}

export class MusicGenerationService {
    static async generate(params: {
        model: string;
        lyrics: string;
        prompt?: string;
        outputFormat?: 'url' | 'hex';
        projectId?: string;
        source?: string;
        sourceId?: string;
        audioSetting?: {
            sample_rate?: number;
            bitrate?: number;
            format?: 'mp3' | 'wav' | 'pcm';
        };
        /** 创建任务后立即回调，便于画布刷新后仍能通过 taskId 恢复轮询 */
        onTaskId?: (taskId: string) => void;
    }): Promise<GenerationResult> {
        try {
            const payload = {
                model: params.model,
                mode: 'music' as const,
                lyrics: params.lyrics,
                prompt: params.prompt,
                outputFormat: params.outputFormat || 'url',
                projectId: params.projectId,
                source: params.source,
                sourceId: params.sourceId,
                audioSetting: params.audioSetting,
            };

            const response = await DefaultService.generateMusic(payload as any);
            const res = (response as any).data;

            if (!res?.task_id) {
                return { status: 'failed', error: response.message || 'No task_id returned' };
            }
            params.onTaskId?.(res.task_id);
            return await GenerationService.pollTask(res.task_id, 'music', params.model, 120);
        } catch (e: any) {
            console.error("Music Gen Error:", e);
            return { status: 'failed', error: e.message || 'Unknown error' };
        }
    }
}

export class LyricsGenerationService {
    static async generate(params: {
        model: string;
        prompt: string;
        mode?: 'write_full_song' | 'edit';
        lyrics?: string;
        title?: string;
        projectId?: string;
        source?: string;
        sourceId?: string;
        /** 创建任务后立即回调，与其它生成类型统一，便于写入节点与刷新后恢复轮询 */
        onTaskId?: (taskId: string) => void;
    }): Promise<{ lyrics: string; songTitle?: string; styleTags?: string }> {
        try {
            const response = await DefaultService.generateMusic({
                model: params.model,
                prompt: params.prompt,
                mode: 'lyrics',
                lyricsMode: params.mode || 'write_full_song',
                seedLyrics: params.lyrics,
                title: params.title,
                projectId: params.projectId,
                source: params.source,
                sourceId: params.sourceId,
            } as any);
            const data = (response as any).data || {};
            if (!data?.task_id) throw new Error('No task_id returned for lyrics generation');

            const taskId = String(data.task_id);
            params.onTaskId?.(taskId);
            const maxAttempts = 120;
            const interval = 2000;
            let attempts = 0;

            while (attempts < maxAttempts) {
                const taskResponse = await DefaultService.getTaskStatus(taskId);
                const taskData = (taskResponse as any).data || {};
                const rawStatus = String(taskData.status || '').toLowerCase();
                const status = rawStatus === 'succeeded' ? 'success' : rawStatus;

                if (status === 'success') {
                    const result = taskData.result || {};
                    const lyrics = (result.lyrics || '').toString();
                    if (!lyrics.trim()) {
                        throw new Error('No lyrics returned');
                    }
                    return {
                        lyrics,
                        songTitle: result.song_title,
                        styleTags: result.style_tags,
                    };
                }

                if (status === 'failed' || status === 'cancelled' || status === 'canceled') {
                    throw new Error(taskData.error || 'Lyrics generation failed');
                }

                await wait(interval);
                attempts += 1;
            }

            throw new Error('Lyrics generation timed out');
        } catch (e: any) {
            console.error("Lyrics Gen Error:", e);
            throw new Error(e?.message || 'Lyrics generation failed');
        }
    }
}
