import { AppNodeData } from '../../../types/node';
import { NodeExecutionStrategy, ExecutionContext } from '../types';
import { generateImage, planStoryboard } from '../../canvasService';

export class ImageStrategy implements NodeExecutionStrategy {
    async execute(context: ExecutionContext): Promise<void> {
        const {
            nodeId, node, inputs, prompt, projectId,
            updateNodeData, addHistoryItem,
            getImageModelDefault, upstreamTexts
        } = context;

        if (node.type !== 'appNode') return;
        const nodeData = node.data as AppNodeData;

        const inputImages: string[] = [];
        inputs.forEach(n => { 
            if (n.type === 'appNode') {
                const data = n.data as AppNodeData;
                if (data.image) {
                    inputImages.push(data.image);
                } else if (data.croppedFrame) {
                    inputImages.push(data.croppedFrame);
                }
            }
        });
        
        const uniqueInputImages = Array.from(new Set(inputImages));
        const currentModel = nodeData.model || getImageModelDefault();

        // Check for storyboard generation
        const isStoryboard = /分镜|storyboard|sequence|shots|frames|json/i.test(prompt);

        if (isStoryboard) {
            try {
                const storyboard = await planStoryboard(prompt, upstreamTexts.join('\n'), projectId);

                if (storyboard.length > 0) {
                    // Unified single-node multi-image mode
                    updateNodeData(nodeId, {
                        status: 'WORKING',
                        title: nodeData.title || `分镜组 (${storyboard.length}张)`
                    });

                    const allImages: string[] = [];
                    const ratio = nodeData.aspectRatio || '16:9';

                    // Sequential generation for each storyboard shot
                    for (let i = 0; i < storyboard.length; i++) {
                        // Check if cancelled before each shot
                        const currentNode = context.nodes.find(n => n.id === nodeId);
                        if (currentNode?.type === 'appNode' &&
                            (currentNode.data.status === 'IDLE' || currentNode.data.error === '已取消')) {
                            console.log('Storyboard generation cancelled');
                            updateNodeData(nodeId, {
                                status: 'IDLE',
                                error: '已取消',
                                images: allImages.length > 0 ? allImages : undefined,
                                image: allImages.length > 0 ? allImages[0] : undefined
                            });
                            return;
                        }

                        const shotPrompt = storyboard[i];
                        try {
                            const res = await generateImage(
                                shotPrompt,
                                currentModel,
                                uniqueInputImages,
                                {
                                    aspectRatio: ratio,
                                    resolution: nodeData.resolution,
                                    count: 1,
                                    styleId: nodeData.styleId,
                                    projectId,
                                    onTaskId: (id) => updateNodeData(nodeId, { taskId: id })
                                }
                            );
                            allImages.push(res[0]);

                            // Update progress in real-time
                            updateNodeData(nodeId, {
                                images: [...allImages],
                                image: allImages[0], // Always show first image as main
                                prompt: `分镜 ${i + 1}/${storyboard.length}: ${shotPrompt.substring(0, 50)}...`
                            });

                            addHistoryItem({
                                id: `gen-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
                                type: 'image',
                                src: res[0],
                                title: `分镜 ${i + 1}`,
                                timestamp: Date.now(),
                                model: currentModel
                            });
                        } catch (e: any) {
                            if (e?.message === '已取消') {
                                updateNodeData(nodeId, {
                                    status: 'IDLE',
                                    error: '已取消',
                                    images: allImages.length > 0 ? allImages : undefined,
                                    image: allImages.length > 0 ? allImages[0] : undefined
                                });
                                return;
                            }
                            console.error(`Failed to generate shot ${i + 1}:`, e);
                        }
                    }

                    // Final update
                    if (allImages.length > 0) {
                        updateNodeData(nodeId, {
                            images: allImages,
                            image: allImages[0],
                            status: 'SUCCESS',
                            prompt: storyboard.join('\n\n'), // Restore combined prompt
                            taskId: undefined
                        });
                    } else {
                        updateNodeData(nodeId, {
                            status: 'ERROR',
                            error: '所有分镜生成失败',
                            taskId: undefined
                        });
                    }
                    return;
                }
            } catch (e) {
                console.warn("Storyboard planning failed, falling back to standard generation", e);
            }
        }
        
        try {
            const res = await generateImage(
                prompt, 
                currentModel, 
                uniqueInputImages, 
                { 
                    aspectRatio: nodeData.aspectRatio || '16:9', 
                    resolution: nodeData.resolution, 
                    count: nodeData.imageCount,
                    styleId: nodeData.styleId,
                    projectId,
                    onTaskId: (id) => updateNodeData(nodeId, { taskId: id })
                }
            );
            updateNodeData(nodeId, { 
                image: res[0], 
                images: res, 
                status: 'SUCCESS' 
            });
            addHistoryItem({
                id: `gen-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
                type: 'image',
                src: res[0],
                title: nodeData.title || 'Generated Image',
                timestamp: Date.now(),
                model: nodeData.model
            });
        } catch (e: any) {
            if (e?.message === '已取消') {
                // 用户主动取消：保持节点为 IDLE，不再向上抛错
                updateNodeData(nodeId, { taskId: undefined, status: 'IDLE', error: '已取消' });
                return;
            }
            updateNodeData(nodeId, { taskId: undefined, status: 'ERROR', error: e?.message });
            throw e;
        } finally {
            updateNodeData(nodeId, { taskId: undefined });
        }
    }
}
