import { AppNodeType, NodeType, InputAsset } from '../types/node';
import { 
    Plus, Type, Image as ImageIcon, Film, Mic2, ScanFace, Brush, Info, Sparkles, ScrollText
} from 'lucide-react';

/** 关联素材展示顺序：视频 → 图像 → 音频 */
const INPUT_ASSET_TYPE_ORDER: Record<InputAsset['type'], number> = { video: 0, image: 1, audio: 2 };
export function sortInputAssetsByTypeOrder(assets: InputAsset[]): InputAsset[] {
    return [...assets].sort((a, b) => INPUT_ASSET_TYPE_ORDER[a.type] - INPUT_ASSET_TYPE_ORDER[b.type]);
}

export const SNAP_THRESHOLD = 8; // Pixels for magnetic snap
export const COLLISION_PADDING = 24; // Spacing when nodes bounce off each other

// Helper to get image dimensions
export const getImageDimensions = (src: string): Promise<{width: number, height: number}> => {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve({width: img.width, height: img.height});
        img.onerror = reject;
        img.src = src;
    });
};

export const getApproxNodeHeight = (node: AppNodeType) => {
    if (node.height) return node.height;
    if (node.measured?.height) return node.measured.height;
    
    const width = node.width || node.measured?.width || 420;

    const data = node.data as any;
    
    if (['VIDEO_ANALYZER', 'IMAGE_EDITOR'].includes(data.type)) return 360;
    if (data.type === NodeType.AUDIO_GENERATOR) return 200;
    
    const aspectRatio = (data.aspectRatio as string) || (data.type === NodeType.INFO_DISPLAY ? '3:4' : '16:9');
    const [w, h] = aspectRatio.split(':').map(Number);
    const extra = (data.type === NodeType.VIDEO_GENERATOR && data.generationMode === 'CUT') ? 36 : 0;
    return ((width * h / w) + extra);
};

export const getNodeBounds = (node: AppNodeType) => {
    const h = node.height || node.measured?.height || getApproxNodeHeight(node);
    const w = node.width || node.measured?.width || 420;
    return { x: node.position.x, y: node.position.y, width: w, height: h, r: node.position.x + w, b: node.position.y + h };
};

export const getNodeNameCN = (t: string) => {
    switch(t) {
        case NodeType.PROMPT_INPUT: return '提示词输入';
        case NodeType.LYRICS_GENERATOR: return '歌词生成';
        case NodeType.IMAGE_GENERATOR: return '图像生成';
        case NodeType.VIDEO_GENERATOR: return '视频生成';
        case NodeType.AUDIO_GENERATOR: return '音频生成';
        case NodeType.VIDEO_ANALYZER: return '视频分析';
        case NodeType.IMAGE_EDITOR: return '图像编辑';
        case NodeType.INFO_DISPLAY: return '素材信息';
        case NodeType.PROMPT_GENERATOR: return '提示词优化';
        default: return t;
    }
};

export const getNodeIcon = (t: string) => {
    switch(t) {
        case NodeType.PROMPT_INPUT: return Type;
        case NodeType.LYRICS_GENERATOR: return ScrollText;
        case NodeType.IMAGE_GENERATOR: return ImageIcon;
        case NodeType.VIDEO_GENERATOR: return Film;
        case NodeType.AUDIO_GENERATOR: return Mic2;
        case NodeType.VIDEO_ANALYZER: return ScanFace;
        case NodeType.IMAGE_EDITOR: return Brush;
        case NodeType.INFO_DISPLAY: return Info;
        case NodeType.PROMPT_GENERATOR: return Sparkles;
        default: return Plus;
    }
};

export const buildComprehensiveStoryboardPrompt = (assetInfo: any): string => {
    const parts: string[] = [];

    // 1. Storyboard Shot Description
    parts.push(`[Storyboard Shot Description]`);
    if (assetInfo.shot) parts.push(`Shot Type: ${assetInfo.shot}`);
    if (assetInfo.desc) parts.push(`Description: ${assetInfo.desc}`);
    if (assetInfo.duration) parts.push(`Duration: ${assetInfo.duration}`);
    if (assetInfo.cameraMovement) parts.push(`Camera Movement: ${assetInfo.cameraMovement}`);
    if (assetInfo.voiceover) parts.push(`Voiceover: "${assetInfo.voiceover}"`);
    
    // 2. Scene Information
    if (assetInfo.resolvedScene) {
        const scene = assetInfo.resolvedScene;
        parts.push(`\n[Scene Information]`);
        parts.push(`Name: ${scene.name}`);
        if (scene.location) parts.push(`Location: ${scene.location}`);
        if (scene.timeOfDay) parts.push(`Time: ${scene.timeOfDay}`);
        if (scene.atmosphere) parts.push(`Atmosphere: ${scene.atmosphere}`);
        if (scene.desc) parts.push(`Description: ${scene.desc}`);
    } else if (assetInfo.sceneId) {
        // Fallback if resolvedScene missing but ID exists (shouldn't happen if initialized correctly)
        parts.push(`\n[Scene Information]`);
        parts.push(`Scene ID: ${assetInfo.sceneId}`);
    }

    // 3. Character Information
    if (assetInfo.resolvedCharacters && assetInfo.resolvedCharacters.length > 0) {
        parts.push(`\n[Character Information]`);
        assetInfo.resolvedCharacters.forEach((char: any, index: number) => {
            parts.push(`Character ${index + 1}: ${char.name}`);
            if (char.gender) parts.push(`- Gender: ${char.gender}`);
            if (char.age) parts.push(`- Age: ${char.age}`);
            if (char.appearance) parts.push(`- Appearance: ${char.appearance}`);
            if (char.clothing) parts.push(`- Clothing: ${char.clothing}`);
        });
    }

    // 4. Prop Information
    if (assetInfo.resolvedProps && assetInfo.resolvedProps.length > 0) {
        parts.push(`\n[Prop Information]`);
        assetInfo.resolvedProps.forEach((prop: any, index: number) => {
            parts.push(`Prop ${index + 1}: ${prop.name}`);
            if (prop.desc) parts.push(`- Description: ${prop.desc}`);
        });
    }

    return parts.join('\n');
};

/**
 * 将包含 @别名 的原始 prompt 转换为使用统一占位符的 prompt，
 * 并返回别名到逻辑角色的映射，供后端进行模型适配。
 *
 * 约定：
 * - 在输入框中用户通过 @图片1 / @视频1 / @音频1 等方式引用素材；
 * - 每个 InputAsset 上会预先填充 logicalRole 和 mentionAlias；
 * - 这里会把 @别名 替换为 `<asset:logicalRole>` 形式的占位符。
 */
export interface AssetMentionMapping {
    alias: string;
    logicalRole: string;
    assetId: string;
}

export function processPromptWithAssets(
    rawPrompt: string,
    assets: InputAsset[] | undefined
): { processedPrompt: string; mappings: AssetMentionMapping[] } {
    if (!assets || assets.length === 0 || !rawPrompt) {
        return { processedPrompt: rawPrompt, mappings: [] };
    }

    let processedPrompt = rawPrompt;
    const mappings: AssetMentionMapping[] = [];

    // 为了避免正则多次构建，先收集所有合法的带别名资产
    const candidates = assets.filter(
        (asset) => !!asset.logicalRole && !!(asset.mentionAlias || asset.label)
    );

    for (const asset of candidates) {
        const alias = asset.mentionAlias || asset.label!;
        const logicalRole = asset.logicalRole!;

        // 匹配 @别名，后面允许是空格、标点或结尾
        const pattern = new RegExp(`@${alias}(?=\\s|[，。,.!?！?]|$)`, 'g');

        if (!pattern.test(processedPrompt)) {
            continue;
        }

        processedPrompt = processedPrompt.replace(pattern, `<asset:${logicalRole}>`);

        mappings.push({
            alias,
            logicalRole,
            assetId: asset.id,
        });
    }

    return { processedPrompt, mappings };
}
