import { NodeExecutionStrategy, ExecutionContext } from '../types';
import { generateVideo } from '../../canvasService';
import { getGenerationStrategy } from '../../videoStrategies';

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

        if (node.type !== 'appNode') return;

        const strategy = await getGenerationStrategy(
            node as any, 
            inputs as any[], 
            prompt, 
            {
                llmModel: getLLMModelDefault(), 
                imageModel: getImageModelDefault() 
            }
        );

        // Parse duration string (e.g. "5s") to number
        const durationStr = node.data.duration;
        const durationNum = durationStr ? parseInt(durationStr.replace(/s$/i, ''), 10) : undefined;

        try {
            const res = await generateVideo(
                strategy.finalPrompt,
                node.data.model || getVideoModelDefault(), 
                { 
                    aspectRatio: node.data.aspectRatio || '16:9', 
                    count: node.data.videoCount || 1, 
                    generationMode: strategy.generationMode,
                    resolution: node.data.resolution,
                    projectId,
                    negativePrompt: node.data.negativePrompt,
                    shotType: node.data.shotType,
                    enableAudio: node.data.enableAudio,
                    cameraControl: node.data.cameraControl,
                    duration: durationNum,
                    onTaskId: (id) => updateNodeData(nodeId, { taskId: id })
                }, 
                strategy.inputImageForGeneration, 
                strategy.videoInput, 
                strategy.referenceImages,
                strategy.audioUrl
            );

            if (res.isFallbackImage) {
                updateNodeData(nodeId, { 
                    image: res.uri, 
                    videoUri: undefined, 
                    error: "Region restricted: Generated preview image instead.", 
                    status: 'SUCCESS' 
                });
                addHistoryItem({
                    id: `gen-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
                    type: 'image',
                    src: res.uri,
                    title: node.data.title || 'Video Preview',
                    timestamp: Date.now(),
                    model: node.data.model
                });
            } else {
                updateNodeData(nodeId, { 
                    videoUri: res.uri, 
                    videoMetadata: res.videoMetadata, 
                    videoUris: res.uris,
                    status: 'SUCCESS'
                });
                addHistoryItem({
                    id: `gen-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
                    type: 'video',
                    src: res.uri,
                    title: node.data.title || 'Generated Video',
                    timestamp: Date.now(),
                    model: node.data.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 });
        }
    }
}
