/**
 * Segment 渲染组件
 * 用于渲染消息链中的各种 Segment 类型
 */

import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
import {
  View,
  Text,
  TouchableOpacity,
  StyleSheet,
  Linking,
  Image,
  GestureResponderEvent,
} from 'react-native';
import { Image as ExpoImage } from 'expo-image';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { VideoPlayerModal } from '../../../../components/common/VideoPlayerModal';
import { 
  MessageSegment, 
  AtSegmentData, 
  ReplySegmentData,
  ImageSegmentData,
  VoiceSegmentData,
  VideoSegmentData,
  FileSegmentData,
  FaceSegmentData,
  LinkSegmentData,
  TextSegmentData,
  MessageResponse,
  UserDTO,
  extractTextFromSegments,
} from '../../../../types/dto';
import { spacing, useAppColors, type AppColors } from '../../../../theme';
import { SenderInfo } from './types';

const IMAGE_MAX_WIDTH = 200;
const IMAGE_MAX_HEIGHT = 260;
const IMAGE_FALLBACK_SIZE = { width: 200, height: 150 };

/** 将非 reply 的 segments 分成：行内文案/@、连续图片组、其它块级（音视频文件等） */
type ContentChunk =
  | { kind: 'inline'; parts: MessageSegment[] }
  | { kind: 'images'; parts: MessageSegment[] }
  | { kind: 'block'; segment: MessageSegment };

function partitionMessageSegments(segments: MessageSegment[]): ContentChunk[] {
  const out: ContentChunk[] = [];
  let inlineBuf: MessageSegment[] = [];
  const flushInline = () => {
    if (inlineBuf.length) {
      out.push({ kind: 'inline', parts: [...inlineBuf] });
      inlineBuf = [];
    }
  };

  for (const s of segments) {
    if (s.type === 'image') {
      flushInline();
      const last = out[out.length - 1];
      if (last?.kind === 'images') {
        last.parts.push(s);
      } else {
        out.push({ kind: 'images', parts: [s] });
      }
    } else if (s.type === 'video' || s.type === 'file' || s.type === 'link' || s.type === 'voice') {
      flushInline();
      out.push({ kind: 'block', segment: s });
    } else if (s.type === 'text' || s.type === 'at' || s.type === 'face') {
      inlineBuf.push(s);
    } else {
      inlineBuf.push(s);
    }
  }
  flushInline();
  return out;
}

// Segment 渲染器 Props
export interface SegmentRendererProps {
  segment: MessageSegment;
  // 当前用户ID，用于判断@是否高亮
  currentUserId?: string;
  // 群成员列表，用于获取@用户的昵称
  memberMap?: Map<string, { nickname: string; user_id: string }>;
  // 是否是自己发送的消息
  isMe: boolean;
  // @点击回调
  onAtPress?: (userId: string) => void;
  // 回复点击回调
  onReplyPress?: (messageId: string) => void;
  // 图片点击回调
  onImagePress?: (url: string) => void;
  // 图片长按回调（触发消息气泡菜单）
  onImageLongPress?: (position?: { x: number; y: number }) => void;
  // 链接点击回调
  onLinkPress?: (url: string) => void;
}

// 回复预览 Props
export interface ReplyPreviewSegmentProps {
  replyData: ReplySegmentData;
  replyMessage?: MessageResponse;
  isMe: boolean;
  onPress?: () => void;
  getSenderInfo?: (senderId: string) => SenderInfo;
}

/**
 * 渲染单个 Segment
 */
export const renderSegment = (
  segment: MessageSegment,
  props: Omit<SegmentRendererProps, 'segment'>
): React.ReactNode => {
  const { isMe } = props;

  switch (segment.type) {
    case 'text':
      return renderTextSegment(segment.data as TextSegmentData, isMe);
    case 'image':
      return renderImageSegment(segment.data as ImageSegmentData, props);
    case 'at':
      return renderAtSegment(segment.data as AtSegmentData, props);
    case 'reply':
      return null; // reply segment 单独处理
    case 'face':
      return renderFaceSegment(segment.data as FaceSegmentData, isMe);
    case 'voice':
      return renderVoiceSegment(segment.data as VoiceSegmentData, isMe);
    case 'video':
      return renderVideoSegment(segment.data as VideoSegmentData, isMe);
    case 'file':
      return renderFileSegment(segment.data as FileSegmentData, isMe);
    case 'link':
      return renderLinkSegment(segment.data as LinkSegmentData, props);
    default:
      return null;
  }
};

/**
 * 渲染文本 Segment
 */
const TextSegmentBody: React.FC<{ data: TextSegmentData; isMe: boolean }> = ({ data, isMe }) => {
  const styles = useSegmentStyles();
  const text = data.content ?? data.text ?? '';
  return (
    <Text
      style={[styles.textContent, isMe ? styles.textMe : styles.textOther]}
      selectable={false}
    >
      {text}
    </Text>
  );
};

const renderTextSegment = (data: TextSegmentData, isMe: boolean): React.ReactNode => {
  const key = `text-${(data.content ?? data.text ?? '').substring(0, 10)}`;
  return <TextSegmentBody key={key} data={data} isMe={isMe} />;
};

/**
 * 渲染图片 Segment
 */
// 图片Segment组件 - 使用Hook获取实际尺寸
const ImageSegment: React.FC<{
  data: ImageSegmentData;
  isMe: boolean;
  onImagePress?: (url: string) => void;
  onImageLongPress?: (position?: { x: number; y: number }) => void;
}> = ({ data, isMe, onImagePress, onImageLongPress }) => {
  const styles = useSegmentStyles();
  const pressPositionRef = useRef({ x: 0, y: 0 });
  const [dimensions, setDimensions] = useState<{ width: number; height: number } | null>(null);
  const [loadError, setLoadError] = useState(false);
  const [currentImageUri, setCurrentImageUri] = useState(data.thumbnail_url || data.url || '');
  const imageUrl = currentImageUri;
  const pressUrl = data.url || data.thumbnail_url || '';
  const stableImageKey = `${data.url || ''}|${data.thumbnail_url || ''}|${data.width || 0}x${data.height || 0}`;
  
  // 如果没有有效的图片URL，显示图片占位符
  const hasValidUrl = !!imageUrl && imageUrl.trim() !== '';
  
  useEffect(() => {
    // 切换消息图片时重置状态，避免列表复用导致旧状态污染
    setCurrentImageUri(data.thumbnail_url || data.url || '');
    setDimensions(null);
    setLoadError(false);
  }, [data.thumbnail_url, data.url]);

  useEffect(() => {
    // 重置状态
    setLoadError(false);
    
    // 如果没有有效的图片URL，设置默认尺寸用于显示占位符
    if (!hasValidUrl) {
      setDimensions(IMAGE_FALLBACK_SIZE);
      return;
    }
    
    // 如果已经有宽高信息，直接使用
    if (data.width && data.height) {
      const aspectRatio = data.width / data.height;
      
      let width = data.width;
      let height = data.height;
      
      if (width > IMAGE_MAX_WIDTH) {
        width = IMAGE_MAX_WIDTH;
        height = width / aspectRatio;
      }
      
      if (height > IMAGE_MAX_HEIGHT) {
        height = IMAGE_MAX_HEIGHT;
        width = height * aspectRatio;
      }
      
      setDimensions({ width: Math.round(width), height: Math.round(height) });
      return;
    }
    
    // 添加超时处理，防止高分辨率图片加载卡住
    const timeoutId = setTimeout(() => {
      setDimensions(prev => prev || IMAGE_FALLBACK_SIZE);
    }, 3000);
    
    // 否则从图片获取实际尺寸
    Image.getSize(
      imageUrl,
      (width, height) => {
        clearTimeout(timeoutId);
        const aspectRatio = width / height;
        
        let newWidth = width;
        let newHeight = height;
        
        if (newWidth > IMAGE_MAX_WIDTH) {
          newWidth = IMAGE_MAX_WIDTH;
          newHeight = newWidth / aspectRatio;
        }
        
        if (newHeight > IMAGE_MAX_HEIGHT) {
          newHeight = IMAGE_MAX_HEIGHT;
          newWidth = newHeight * aspectRatio;
        }
        
        setDimensions({ width: Math.round(newWidth), height: Math.round(newHeight) });
      },
      () => {
        clearTimeout(timeoutId);
        // 获取失败时使用默认 4:3 比例
        setDimensions(IMAGE_FALLBACK_SIZE);
      }
    );
    
    return () => clearTimeout(timeoutId);
  }, [imageUrl, data.width, data.height, hasValidUrl]);
  
  // 记录按压位置
  const handlePressIn = (event: GestureResponderEvent) => {
    const { pageX, pageY } = event.nativeEvent;
    pressPositionRef.current = { x: pageX, y: pageY };
  };

  // 处理长按
  const handleLongPress = () => {
    onImageLongPress?.(pressPositionRef.current);
  };

  // 没有有效URL或加载失败时显示占位符
  if (!hasValidUrl || loadError) {
    return (
      <TouchableOpacity
        style={[styles.imageContainer, isMe ? styles.imageMe : styles.imageOther]}
        onPressIn={handlePressIn}
        onPress={() => hasValidUrl && onImagePress?.(pressUrl)}
        onLongPress={handleLongPress}
        delayLongPress={500}
        activeOpacity={0.9}
      >
        <View
          style={{
            width: IMAGE_FALLBACK_SIZE.width,
            height: IMAGE_FALLBACK_SIZE.height,
            borderRadius: 8,
            backgroundColor: 'rgba(0,0,0,0.1)',
            justifyContent: 'center',
            alignItems: 'center',
          }}
        >
          <MaterialCommunityIcons name="image" size={32} color="#999" />
          <Text style={{ color: '#999', fontSize: 12, marginTop: 4 }}>图片</Text>
        </View>
      </TouchableOpacity>
    );
  }
  
  // 初始加载时显示占位
  if (!dimensions) {
    return (
      <TouchableOpacity
        style={[styles.imageContainer, isMe ? styles.imageMe : styles.imageOther]}
        onPressIn={handlePressIn}
        onPress={() => onImagePress?.(pressUrl)}
        onLongPress={handleLongPress}
        delayLongPress={500}
        activeOpacity={0.9}
      >
        <View
          style={{
            width: IMAGE_FALLBACK_SIZE.width,
            height: IMAGE_FALLBACK_SIZE.height,
            borderRadius: 8,
            backgroundColor: 'rgba(0,0,0,0.1)',
          }}
        />
      </TouchableOpacity>
    );
  }
  
  return (
    <TouchableOpacity
      style={[styles.imageContainer, isMe ? styles.imageMe : styles.imageOther]}
      onPressIn={handlePressIn}
      onPress={() => onImagePress?.(pressUrl)}
      onLongPress={handleLongPress}
      delayLongPress={500}
      activeOpacity={0.9}
    >
      <ExpoImage
        source={{ uri: imageUrl }}
        style={{
          width: dimensions.width,
          height: dimensions.height,
          borderRadius: 8,
        }}
        recyclingKey={stableImageKey}
        contentFit="cover"
        cachePolicy="memory-disk"
        priority="normal"
        transition={200}
        onLoadStart={() => {
          setLoadError(false);
        }}
        onError={() => {
          // 缩略图失败时自动回退原图，降低跳转定位后的白块/丢图概率
          if (data.thumbnail_url && data.url && imageUrl === data.thumbnail_url) {
            setCurrentImageUri(data.url);
            return;
          }
          setLoadError(true);
        }}
      />
    </TouchableOpacity>
  );
};

const renderImageSegment = (
  data: ImageSegmentData, 
  props: Omit<SegmentRendererProps, 'segment'>
): React.ReactNode => {
  const { onImagePress, onImageLongPress, isMe } = props;
  return <ImageSegment data={data} isMe={isMe} onImagePress={onImagePress} onImageLongPress={onImageLongPress} />;
};

/**
 * 渲染 @ Segment
 */
const AtSegmentBody: React.FC<{
  data: AtSegmentData;
  props: Omit<SegmentRendererProps, 'segment'>;
}> = ({ data, props }) => {
  const styles = useSegmentStyles();
  const { currentUserId, memberMap, onAtPress, isMe } = props;
  const isAtMe = data.user_id === currentUserId || data.user_id === 'all';
  let displayName: string;
  if (data.user_id === 'all') {
    displayName = '所有人';
  } else {
    const member = memberMap?.get(data.user_id);
    displayName = member?.nickname || data.nickname || '用户';
  }
  return (
    <Text
      style={[
        styles.atText,
        isMe ? styles.atTextMe : styles.atTextOther,
        isAtMe && styles.atHighlight,
      ]}
      onPress={() => data.user_id !== 'all' && onAtPress?.(data.user_id)}
    >
      @{displayName}
    </Text>
  );
};

const renderAtSegment = (
  data: AtSegmentData,
  props: Omit<SegmentRendererProps, 'segment'>
): React.ReactNode => <AtSegmentBody key={`at-${data.user_id}`} data={data} props={props} />;

/**
 * 渲染表情 Segment
 */
const FaceSegmentBody: React.FC<{ data: FaceSegmentData }> = ({ data }) => {
  const styles = useSegmentStyles();
  if (data.url) {
    return (
      <ExpoImage
        source={{ uri: data.url }}
        style={styles.faceImage}
        contentFit="cover"
        cachePolicy="memory"
      />
    );
  }
  return (
    <Text style={styles.faceText}>
      [{data.name || `表情${data.id}`}]
    </Text>
  );
};

const renderFaceSegment = (data: FaceSegmentData, _isMe: boolean): React.ReactNode => (
  <FaceSegmentBody key={`face-${data.id}`} data={data} />
);

/**
 * 渲染语音 Segment
 */
const VoiceSegmentBody: React.FC<{ data: VoiceSegmentData; isMe: boolean }> = ({ data, isMe }) => {
  const styles = useSegmentStyles();
  const themeColors = useAppColors();
  return (
    <TouchableOpacity
      style={[styles.voiceContainer, isMe ? styles.voiceMe : styles.voiceOther]}
      activeOpacity={0.7}
    >
      <MaterialCommunityIcons
        name="microphone"
        size={20}
        color={isMe ? themeColors.primary.contrast : themeColors.chat.textTertiary}
      />
      <Text style={[styles.voiceDuration, isMe ? styles.textMe : styles.textOther]}>
        {data.duration ? `${data.duration}"` : '语音'}
      </Text>
    </TouchableOpacity>
  );
};

const renderVoiceSegment = (data: VoiceSegmentData, isMe: boolean): React.ReactNode => (
  <VoiceSegmentBody key={`voice-${data.url}`} data={data} isMe={isMe} />
);

/**
 * 视频 Segment 组件 - 支持点击播放
 */
const VideoSegment: React.FC<{ data: VideoSegmentData; isMe: boolean }> = ({ data, isMe }) => {
  const styles = useSegmentStyles();
  const themeColors = useAppColors();
  const [playerVisible, setPlayerVisible] = useState(false);

  const handlePress = useCallback(() => {
    if (data.url) {
      setPlayerVisible(true);
    }
  }, [data.url]);

  return (
    <>
      <TouchableOpacity
        style={[styles.videoContainer, isMe ? styles.videoMe : styles.videoOther]}
        onPress={handlePress}
        activeOpacity={0.7}
      >
        {data.thumbnail_url ? (
          <ExpoImage
            source={{ uri: data.thumbnail_url }}
            style={styles.videoThumbnail}
            contentFit="cover"
          />
        ) : (
          <View style={styles.videoPlaceholder}>
            <MaterialCommunityIcons name="video" size={32} color={themeColors.primary.contrast} />
          </View>
        )}
        <View style={styles.videoPlayIcon}>
          <MaterialCommunityIcons name="play-circle" size={40} color={themeColors.primary.contrast} />
        </View>
        {data.duration && (
          <Text style={styles.videoDuration}>{formatDuration(data.duration)}</Text>
        )}
      </TouchableOpacity>

      <VideoPlayerModal
        visible={playerVisible}
        url={data.url}
        onClose={() => setPlayerVisible(false)}
      />
    </>
  );
};

const renderVideoSegment = (data: VideoSegmentData, isMe: boolean): React.ReactNode => {
  return <VideoSegment key={`video-${data.url}`} data={data} isMe={isMe} />;
};

/**
 * 渲染文件 Segment
 */
const FileSegmentBody: React.FC<{ data: FileSegmentData; isMe: boolean }> = ({ data, isMe }) => {
  const styles = useSegmentStyles();
  const themeColors = useAppColors();
  const fileSize = data.size ? formatFileSize(data.size) : '';
  return (
    <TouchableOpacity
      style={[styles.fileContainer, isMe ? styles.fileMe : styles.fileOther]}
      activeOpacity={0.7}
    >
      <View style={styles.fileIcon}>
        <MaterialCommunityIcons
          name="file-document"
          size={28}
          color={isMe ? themeColors.primary.contrast : themeColors.primary.main}
        />
      </View>
      <View style={styles.fileInfo}>
        <Text
          style={[styles.fileName, isMe ? styles.textMe : styles.textOther]}
          numberOfLines={1}
        >
          {data.name}
        </Text>
        {fileSize ? <Text style={styles.fileSize}>{fileSize}</Text> : null}
      </View>
    </TouchableOpacity>
  );
};

const renderFileSegment = (data: FileSegmentData, isMe: boolean): React.ReactNode => (
  <FileSegmentBody key={`file-${data.url}`} data={data} isMe={isMe} />
);

/**
 * 渲染链接 Segment
 */
const LinkSegmentBody: React.FC<{
  data: LinkSegmentData;
  props: Omit<SegmentRendererProps, 'segment'>;
}> = ({ data, props }) => {
  const styles = useSegmentStyles();
  const { onLinkPress, isMe } = props;

  const handlePress = async () => {
    if (onLinkPress) {
      onLinkPress(data.url);
    } else {
      try {
        const supported = await Linking.canOpenURL(data.url);
        if (supported) {
          await Linking.openURL(data.url);
        } else {
          console.warn('无法打开链接:', data.url);
        }
      } catch (error) {
        console.warn('打开链接失败:', error);
      }
    }
  };

  return (
    <TouchableOpacity
      style={[styles.linkContainer, isMe ? styles.linkMe : styles.linkOther]}
      onPress={handlePress}
      activeOpacity={0.7}
    >
      {data.image ? (
        <ExpoImage source={{ uri: data.image }} style={styles.linkImage} contentFit="cover" cachePolicy="memory" />
      ) : null}
      <View style={styles.linkContent}>
        <Text style={styles.linkTitle} numberOfLines={2}>
          {data.title || data.url}
        </Text>
        {data.description ? (
          <Text style={styles.linkDescription} numberOfLines={2}>
            {data.description}
          </Text>
        ) : null}
        <Text style={styles.linkUrl} numberOfLines={1}>
          {(() => {
            try {
              return new URL(data.url).hostname;
            } catch {
              return data.url;
            }
          })()}
        </Text>
      </View>
    </TouchableOpacity>
  );
};

const renderLinkSegment = (
  data: LinkSegmentData,
  props: Omit<SegmentRendererProps, 'segment'>
): React.ReactNode => <LinkSegmentBody key={`link-${data.url}`} data={data} props={props} />;

/**
 * 回复预览组件（用于消息气泡内显示回复引用）
 */
export const ReplyPreviewSegment: React.FC<ReplyPreviewSegmentProps> = ({
  replyData,
  replyMessage,
  isMe,
  onPress,
  getSenderInfo,
}) => {
  const themeColors = useAppColors();
  const styles = useMemo(() => createSegmentStyles(themeColors), [themeColors]);

  if (!replyMessage) {
    // 如果没有引用消息详情，只显示引用ID
    return (
      <TouchableOpacity
        style={[styles.replyPreview, isMe ? styles.replyMe : styles.replyOther]}
        onPress={onPress}
        activeOpacity={0.7}
      >
        <View style={styles.replyLine} />
        <View style={styles.replyContent}>
          <Text style={styles.replyText} numberOfLines={2}>
            引用消息
          </Text>
        </View>
      </TouchableOpacity>
    );
  }
  
  // 获取发送者信息 - 优先使用 replyMessage.sender
  let senderName = '';
  if (replyMessage.sender?.nickname) {
    senderName = replyMessage.sender.nickname;
  } else if (replyMessage.sender?.username) {
    senderName = replyMessage.sender.username;
  } else if (getSenderInfo && replyMessage.sender_id) {
    const info = getSenderInfo(replyMessage.sender_id);
    senderName = info.nickname;
  }

  // 如果还是没有昵称，显示"对方"
  if (!senderName || senderName === '用户') {
    senderName = '对方';
  }

  // 获取预览内容 - 使用 extractTextFromSegments 从 segments 提取
  let previewContent = '';
  if (replyMessage.segments?.length) {
    // 检查是否有图片/语音/视频/文件
    const hasImage = replyMessage.segments.some(s => s.type === 'image');
    const hasVoice = replyMessage.segments.some(s => s.type === 'voice');
    const hasVideo = replyMessage.segments.some(s => s.type === 'video');
    const hasFile = replyMessage.segments.some(s => s.type === 'file');

    if (hasImage) {
      const imageCount = replyMessage.segments.filter(seg => seg.type === 'image').length;
      previewContent = imageCount > 1 ? `[${imageCount}张图片]` : '[图片]';
    } else if (hasVoice) {
      previewContent = '[语音]';
    } else if (hasVideo) {
      previewContent = '[视频]';
    } else if (hasFile) {
      previewContent = '[文件]';
    } else {
      // 从文本 segments 提取
      previewContent = extractTextFromSegments(replyMessage.segments);
    }
  }
  
  return (
    <TouchableOpacity
      style={[styles.replyPreview, isMe ? styles.replyMe : styles.replyOther]}
      onPress={onPress}
      activeOpacity={0.7}
    >
      <View style={styles.replyLine} />
      <View style={styles.replyContent}>
        <Text style={styles.replySender} numberOfLines={1}>
          {senderName}:
        </Text>
        <Text
          style={styles.replyText}
          numberOfLines={1}
          ellipsizeMode="tail"
        >
          {previewContent}
        </Text>
      </View>
    </TouchableOpacity>
  );
};

/**
 * 渲染完整的消息链（多个 Segment 组合）
 */
export const MessageSegmentsRenderer: React.FC<{
  segments: MessageSegment[];
  isMe: boolean;
  currentUserId?: string;
  memberMap?: Map<string, { nickname: string; user_id: string }>;
  replyMessage?: MessageResponse;
  onAtPress?: (userId: string) => void;
  onReplyPress?: (messageId: string) => void;
  onImagePress?: (url: string) => void;
  onImageLongPress?: () => void;
  onLinkPress?: (url: string) => void;
  getSenderInfo?: (senderId: string) => SenderInfo;
}> = ({
  segments,
  isMe,
  currentUserId,
  memberMap,
  replyMessage,
  onAtPress,
  onReplyPress,
  onImagePress,
  onImageLongPress,
  onLinkPress,
  getSenderInfo,
}) => {
  const themeColors = useAppColors();
  const segStyles = useMemo(() => createSegmentStyles(themeColors), [themeColors]);

  const replySegment = segments.find(s => s.type === 'reply');
  const otherSegments = segments.filter(s => s.type !== 'reply');
  const chunks = partitionMessageSegments(otherSegments);

  const renderProps = {
    isMe,
    currentUserId,
    memberMap,
    onAtPress,
    onReplyPress,
    onImagePress,
    onImageLongPress,
    onLinkPress,
  };

  return (
    <SegmentStylesContext.Provider value={segStyles}>
      <View style={segStyles.segmentsContainer}>
        {replySegment ? (
          <ReplyPreviewSegment
            replyData={replySegment.data as ReplySegmentData}
            replyMessage={replyMessage}
            isMe={isMe}
            onPress={() => onReplyPress?.((replySegment.data as ReplySegmentData).id)}
            getSenderInfo={getSenderInfo}
          />
        ) : null}

        <View style={segStyles.segmentsColumn}>
          {chunks.map((chunk, i) => {
            if (chunk.kind === 'inline') {
              return (
                <View key={`inl-${i}`} style={segStyles.inlineChunk}>
                  {chunk.parts.map((segment, j) => (
                    <React.Fragment
                      key={`segment-${segment.type}-${(segment as any)?.data?.url || (segment as any)?.data?.id || (segment as any)?.data?.user_id || j}`}
                    >
                      {renderSegment(segment, renderProps)}
                    </React.Fragment>
                  ))}
                </View>
              );
            }
            if (chunk.kind === 'images') {
              return (
                <View key={`imgs-${i}`} style={segStyles.imagesChunk}>
                  {chunk.parts.map((segment, j) => (
                    <View
                      key={`img-${(segment.data as ImageSegmentData)?.url || j}`}
                      style={j < chunk.parts.length - 1 ? segStyles.imageStackItem : segStyles.imageStackItemLast}
                    >
                      {renderSegment(segment, renderProps)}
                    </View>
                  ))}
                </View>
              );
            }
            return (
              <View key={`blk-${i}`} style={segStyles.blockChunk}>
                {renderSegment(chunk.segment, renderProps)}
              </View>
            );
          })}
        </View>
      </View>
    </SegmentStylesContext.Provider>
  );
};

// 辅助函数：格式化文件大小
const formatFileSize = (bytes: number): string => {
  if (bytes < 1024) return `${bytes} B`;
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
  return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB`;
};

// 辅助函数：格式化时长
const formatDuration = (seconds: number): string => {
  const mins = Math.floor(seconds / 60);
  const secs = seconds % 60;
  return mins > 0 ? `${mins}:${secs.toString().padStart(2, '0')}` : `0:${secs.toString().padStart(2, '0')}`;
};

function createSegmentStyles(colors: AppColors) {
  return StyleSheet.create({
  // 容器
  segmentsContainer: {
    flexDirection: 'column',
    width: '100%',
  },
  segmentsColumn: {
    flexDirection: 'column',
    width: '100%',
  },
  inlineChunk: {
    flexDirection: 'row',
    flexWrap: 'wrap',
    alignItems: 'flex-end',
    width: '100%',
  },
  imagesChunk: {
    width: '100%',
  },
  imageStackItem: {
    width: '100%',
    marginBottom: 6,
  },
  imageStackItemLast: {
    width: '100%',
  },
  blockChunk: {
    width: '100%',
    marginTop: 2,
  },

  // 文本 - 适配暗色模式
  textContent: {
    fontSize: 17.5,
    lineHeight: 25,
    letterSpacing: 0.1,
    fontWeight: '400',
  },
  textMe: {
    color: colors.chat.textPrimary,
  },
  textOther: {
    color: colors.chat.textPrimary,
  },

  // @提及 - 微信/QQ 风格：更精致的高亮
  atText: {
    fontSize: 16,
    lineHeight: 22,
    fontWeight: '500',
  },
  atTextMe: {
    color: '#1A5F9E',  // 深蓝色，在绿色背景上更清晰
  },
  atTextOther: {
    color: colors.chat.link,
  },
  atHighlight: {
    backgroundColor: 'rgba(74, 136, 199, 0.15)',
    borderRadius: 4,
    paddingHorizontal: 3,
  },

  // 图片 - QQ风格：保持原始宽高比
  imageContainer: {
    borderRadius: 12,
    overflow: 'hidden',
    marginTop: 4,
    shadowColor: colors.chat.shadow,
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.15,
    shadowRadius: 4,
    elevation: 4,
  },
  imageMe: {
    borderBottomRightRadius: 4,
  },
  imageOther: {
    borderBottomLeftRadius: 4,
  },
  // 移除固定的 image 样式，改为在组件中动态计算

  // 表情 - QQ风格：更大的表情
  faceImage: {
    width: 28,
    height: 28,
  },
  faceText: {
    fontSize: 16,
    color: '#666',
  },

  // 语音 - QQ风格：更明显的背景
  voiceContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: spacing.md,
    paddingVertical: spacing.sm + 2,
    borderRadius: 20,
    minWidth: 100,
    shadowColor: colors.chat.shadow,
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.1,
    shadowRadius: 2,
    elevation: 2,
  },
  voiceMe: {
    backgroundColor: 'rgba(255, 255, 255, 0.25)',
  },
  voiceOther: {
    backgroundColor: 'rgba(0, 0, 0, 0.06)',
  },
  voiceDuration: {
    marginLeft: spacing.sm,
    fontSize: 15,
    fontWeight: '500',
  },

  // 视频 - QQ风格：更大的缩略图
  videoContainer: {
    borderRadius: 16,
    overflow: 'hidden',
    width: 220,
    height: 165,
    shadowColor: colors.chat.shadow,
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.15,
    shadowRadius: 4,
    elevation: 4,
  },
  videoMe: {
    borderBottomRightRadius: 6,
  },
  videoOther: {
    borderBottomLeftRadius: 6,
  },
  videoThumbnail: {
    width: '100%',
    height: '100%',
  },
  videoPlaceholder: {
    width: '100%',
    height: '100%',
    backgroundColor: 'linear-gradient(135deg, #333 0%, #555 100%)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  videoPlayIcon: {
    position: 'absolute',
    top: '50%',
    left: '50%',
    marginTop: -24,
    marginLeft: -24,
    backgroundColor: 'rgba(0, 0, 0, 0.4)',
    borderRadius: 24,
    padding: 4,
  },
  videoDuration: {
    position: 'absolute',
    bottom: 10,
    right: 10,
    color: colors.primary.contrast,
    fontSize: 13,
    fontWeight: '600',
    backgroundColor: 'rgba(0, 0, 0, 0.6)',
    paddingHorizontal: 8,
    paddingVertical: 3,
    borderRadius: 6,
    overflow: 'hidden',
  },

  // 文件 - QQ风格：卡片式设计
  fileContainer: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: spacing.md,
    borderRadius: 16,
    minWidth: 220,
    maxWidth: 300,
    shadowColor: colors.chat.shadow,
    shadowOffset: { width: 0, height: 1 },
    shadowOpacity: 0.08,
    shadowRadius: 2,
    elevation: 2,
  },
  fileMe: {
    backgroundColor: 'rgba(255, 255, 255, 0.25)',
  },
  fileOther: {
    backgroundColor: colors.chat.surfaceRaised,
  },
  fileIcon: {
    marginRight: spacing.md,
    width: 44,
    height: 44,
    borderRadius: 12,
    backgroundColor: 'rgba(255, 107, 53, 0.15)',
    justifyContent: 'center',
    alignItems: 'center',
  },
  fileInfo: {
    flex: 1,
  },
  fileName: {
    fontSize: 15,
    fontWeight: '600',
    color: colors.chat.textPrimary,
  },
  fileSize: {
    fontSize: 13,
    color: colors.chat.textSecondary,
    marginTop: 4,
    fontWeight: '500',
  },

  // 链接 - QQ风格：卡片式设计
  linkContainer: {
    borderRadius: 16,
    overflow: 'hidden',
    maxWidth: 280,
    backgroundColor: colors.chat.card,
    shadowColor: colors.chat.shadow,
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  linkMe: {
    backgroundColor: 'rgba(255, 255, 255, 0.95)',
  },
  linkOther: {
    backgroundColor: colors.chat.card,
  },
  linkImage: {
    width: '100%',
    height: 140,
  },
  linkContent: {
    padding: spacing.md,
  },
  linkTitle: {
    fontSize: 15,
    fontWeight: '600',
    color: colors.chat.textPrimary,
    lineHeight: 20,
  },
  linkDescription: {
    fontSize: 13,
    color: colors.chat.textTertiary,
    marginTop: 6,
    lineHeight: 18,
  },
  linkUrl: {
    fontSize: 12,
    color: '#8E8E93',
    marginTop: 6,
    fontWeight: '500',
  },

  // 回复预览 - Telegram风格：左侧色条 + 简洁背景
  replyPreview: {
    flexDirection: 'row',
    alignItems: 'center',
    marginBottom: 0,
    paddingVertical: spacing.sm,
    paddingHorizontal: spacing.sm + 2,
    borderRadius: 6,
    width: '100%',
    minWidth: 200,
    gap: 8,
    shadowColor: 'transparent',
    shadowOffset: { width: 0, height: 0 },
    shadowOpacity: 0,
    shadowRadius: 0,
    elevation: 0,
  },
  replyMe: {
    backgroundColor: 'rgba(74, 136, 199, 0.12)',
  },
  replyOther: {
    backgroundColor: 'rgba(0, 0, 0, 0.03)',
  },
  replyLine: {
    width: 3,
    alignSelf: 'stretch',
    minHeight: 28,
    borderRadius: 2,
    backgroundColor: colors.chat.link,
  },
  replyContent: {
    flex: 1,
    flexDirection: 'row',
    alignItems: 'center',
    flexWrap: 'nowrap',
    minWidth: 0,
  },
  replySender: {
    fontSize: 13,
    fontWeight: '600',
    color: colors.chat.link,
    marginRight: 6,
    flexShrink: 0,
  },
  replyText: {
    fontSize: 13,
    color: colors.chat.textTertiary,
    flex: 1,
    flexShrink: 1,
  },
  });
}

type SegmentStyles = ReturnType<typeof createSegmentStyles>;

const SegmentStylesContext = React.createContext<SegmentStyles | null>(null);

function useSegmentStyles(): SegmentStyles {
  const ctx = React.useContext(SegmentStylesContext);
  if (!ctx) {
    throw new Error('useSegmentStyles 必须在 MessageSegmentsRenderer 内使用');
  }
  return ctx;
}

export default MessageSegmentsRenderer;