import React, { useState, useEffect, useRef } from 'react';
import { useParams, Link, useNavigate, useLocation } from 'react-router-dom';
import apiClient from '../utils/apiClient';
import configService from '../utils/configService';
import tools from '../utils/tools';
import { ArrowLeft, Clock, Users, User, Calendar, Play, Pause, Volume2, MessageCircle, Edit, Trash2, Settings, Save, X, Edit3, Brain, Sparkles, Download, ArrowDown, RefreshCw, RefreshCwOff, Image, QrCode, MoreVertical, Upload, ChevronLeft, ChevronRight, Loader, Lock, Unlock, Eye, EyeOff, Copy, Check } from 'lucide-react';
import { buildApiUrl, API_ENDPOINTS, API_BASE_URL } from '../config/api';
import ContentViewer from '../components/ContentViewer';
import MarkdownRenderer from '../components/MarkdownRenderer';
import TagDisplay from '../components/TagDisplay';
import ConfirmDialog from '../components/ConfirmDialog';
import Toast from '../components/Toast';
import PageLoading from '../components/PageLoading';
import QRCodeModal from '../components/QRCodeModal';
import Dropdown from '../components/Dropdown';
import exportService from '../services/exportService';
import { Tabs } from 'antd';
import './MeetingDetails.css';

const { TabPane } = Tabs;

const MeetingDetails = ({ user }) => {
  const { meeting_id } = useParams();
  const navigate = useNavigate();
  const location = useLocation();
  const [meeting, setMeeting] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState('');
  const [isPlaying, setIsPlaying] = useState(false);
  const [currentTime, setCurrentTime] = useState(0);
  const [duration, setDuration] = useState(0);
  const [volume, setVolume] = useState(1);
  const [transcript, setTranscript] = useState([]);
  const [showTranscript, setShowTranscript] = useState(true);
  const [audioUrl, setAudioUrl] = useState(null);
  const [audioFileName, setAudioFileName] = useState(null);
  const [deleteConfirmInfo, setDeleteConfirmInfo] = useState(null);
  const [showSpeakerEdit, setShowSpeakerEdit] = useState(false);
  const [editingSpeakers, setEditingSpeakers] = useState({});
  const [speakerList, setSpeakerList] = useState([]);
  const [showTranscriptEdit, setShowTranscriptEdit] = useState(false);
  const [transcriptionStatus, setTranscriptionStatus] = useState(null);
  const [transcriptionProgress, setTranscriptionProgress] = useState(0);
  const [statusCheckInterval, setStatusCheckInterval] = useState(null);
  const [autoScrollEnabled, setAutoScrollEnabled] = useState(false); // 控制自动滚动
  const [editingTranscriptIndex, setEditingTranscriptIndex] = useState(-1);
  const [editingTranscripts, setEditingTranscripts] = useState({});
  const [currentSubtitle, setCurrentSubtitle] = useState('');
  const [currentSpeaker, setCurrentSpeaker] = useState('');
  const [showSummaryModal, setShowSummaryModal] = useState(false);
  const [summaryLoading, setSummaryLoading] = useState(false);
  const [summaryResult, setSummaryResult] = useState(null);
  const [userPrompt, setUserPrompt] = useState('');
  const [summaryHistory, setSummaryHistory] = useState([]);
  const [promptList, setPromptList] = useState([]);
  const [selectedPromptId, setSelectedPromptId] = useState(null);
  const [currentHighlightIndex, setCurrentHighlightIndex] = useState(-1);
  const [summaryTaskId, setSummaryTaskId] = useState(null);
  const [summaryTaskStatus, setSummaryTaskStatus] = useState(null);
  const [summaryTaskProgress, setSummaryTaskProgress] = useState(0);
  const [summaryTaskMessage, setSummaryTaskMessage] = useState('');
  const [summaryPollInterval, setSummaryPollInterval] = useState(null);
  const [toasts, setToasts] = useState([]);
  const [showQRModal, setShowQRModal] = useState(false);
  const [audioFile, setAudioFile] = useState(null);
  const [isUploading, setIsUploading] = useState(false);
  const [showUploadConfirm, setShowUploadConfirm] = useState(false);
  const [maxFileSize, setMaxFileSize] = useState(100 * 1024 * 1024); // 默认100MB
  const [uploadError, setUploadError] = useState('');

  // 访问密码相关状态
  const [accessPassword, setAccessPassword] = useState(null);
  const [passwordEnabled, setPasswordEnabled] = useState(false);
  const [showPassword, setShowPassword] = useState(false);
  const [passwordCopied, setPasswordCopied] = useState(false);
  const [passwordLoading, setPasswordLoading] = useState(false);

  // 音频加载状态
  const [audioLoading, setAudioLoading] = useState(true); // 音频是否正在加载
  const [audioCanPlay, setAudioCanPlay] = useState(false); // 音频是否可以播放
  const [audioBuffering, setAudioBuffering] = useState(false); // 音频是否正在缓冲
  const [audioError, setAudioError] = useState(null); // 音频加载错误

  // 导航相关状态
  const [navigationInfo, setNavigationInfo] = useState({
    prev_meeting_id: null,
    next_meeting_id: null,
    current_index: null,
    total_count: null
  });
  const [filterContext, setFilterContext] = useState({
    filterType: 'all',
    searchQuery: '',
    selectedTags: []
  });

  const audioRef = useRef(null);
  const transcriptRefs = useRef([]);

  // Toast 辅助函数
  const showToast = (message, type = 'info') => {
    const id = Date.now();
    setToasts(prev => [...prev, { id, message, type }]);
  };

  const removeToast = (id) => {
    setToasts(prev => prev.filter(toast => toast.id !== id));
  };

  // 获取从Dashboard传递的筛选上下文
  useEffect(() => {
    if (location.state?.filterContext) {
      setFilterContext(location.state.filterContext);
    }
  }, [location.state]);

  useEffect(() => {
    fetchMeetingDetails();
    loadFileSizeConfig();
    fetchPromptList();

    // Cleanup interval on unmount
    return () => {
      if (statusCheckInterval) {
        console.log('组件卸载，清理转录状态轮询定时器');
        clearInterval(statusCheckInterval);
        setStatusCheckInterval(null);
      }
      if (summaryPollInterval) {
        console.log('组件卸载，清理总结任务轮询定时器');
        clearInterval(summaryPollInterval);
        setSummaryPollInterval(null);
      }
      // 停止音频播放
      if (audioRef.current) {
        audioRef.current.pause();
        audioRef.current.currentTime = 0;
      }
    };
  }, [meeting_id]);

  // 监听audioUrl变化，确保音频正确重置
  useEffect(() => {
    // 当audioUrl变化时，停止当前播放并重置audio元素
    if (audioRef.current) {
      audioRef.current.pause();
      audioRef.current.currentTime = 0;
      audioRef.current.load(); // 重新加载audio元素
    }
  }, [audioUrl]);
  
  // Cleanup interval when status changes
  useEffect(() => {
    if (transcriptionStatus) {
      // 如果转录已完成、失败或取消，清除轮询
      if (['completed', 'failed', 'error', 'cancelled'].includes(transcriptionStatus.status)) {
        if (statusCheckInterval) {
          clearInterval(statusCheckInterval);
          setStatusCheckInterval(null);
        }
      }
    }
  }, [transcriptionStatus, statusCheckInterval]);

  const refreshTranscriptData = async () => {
    try {
      const baseUrl = "";
      const transcriptEndpoint = API_ENDPOINTS?.MEETINGS?.TRANSCRIPT?.(meeting_id) || `/api/meetings/${meeting_id}/transcript`;
      
      // 只刷新转录数据，不显示loading
      const transcriptResponse = await apiClient.get(`${baseUrl}${transcriptEndpoint}`);
      setTranscript(transcriptResponse.data);
      
      // 更新发言人列表
      const allSpeakerIds = transcriptResponse.data
        .map(item => item.speaker_id)
        .filter(speakerId => speakerId !== null && speakerId !== undefined);
      
      const uniqueSpeakers = [...new Set(allSpeakerIds)]
        .map(speakerId => {
          const segment = transcriptResponse.data.find(item => item.speaker_id === speakerId);
          return {
            speaker_id: speakerId,
            speaker_tag: segment ? (segment.speaker_tag || `发言人 ${speakerId}`) : `发言人 ${speakerId}`
          };
        })
        .sort((a, b) => a.speaker_id - b.speaker_id);
      
      setSpeakerList(uniqueSpeakers);
      console.log('转录数据已刷新，无loading状态');
      
    } catch (error) {
      console.error('刷新转录数据失败:', error);
    }
  };

  const startStatusPolling = (taskId) => {
    // Clear existing interval
    if (statusCheckInterval) {
      clearInterval(statusCheckInterval);
      setStatusCheckInterval(null);
    }
    
    // Poll every 3 seconds
    const interval = setInterval(async () => {
      try {
        const statusResponse = await apiClient.get(buildApiUrl(API_ENDPOINTS.TASKS.TRANSCRIPTION_STATUS(taskId)));
        const status = statusResponse.data;
        
        setTranscriptionStatus(status);
        setTranscriptionProgress(status.progress || 0);
        
        // Stop polling if task is completed or failed
        if (['completed', 'failed', 'error', 'cancelled'].includes(status.status)) {
          clearInterval(interval);
          setStatusCheckInterval(null);
          
          // Refresh transcript data only if completed successfully
          if (status.status === 'completed') {
            console.log('转录完成，刷新转录数据（无loading）');
            await refreshTranscriptData();
          } else {
            console.log('转录失败或取消，状态:', status.status);
          }
          
          // 再次确保清除状态
          setTranscriptionStatus(status);
        }
      } catch (error) {
        console.error('Failed to fetch transcription status:', error);
        // Clear interval on error to prevent endless polling
        clearInterval(interval);
        setStatusCheckInterval(null);
      }
    }, 3000);
    
    setStatusCheckInterval(interval);
  };

  const fetchMeetingDetails = async () => {
    try {
      setLoading(true);
      
      // Fallback URL construction in case config fails
      const baseUrl = ""
      const detailEndpoint = API_ENDPOINTS?.MEETINGS?.DETAIL?.(meeting_id) || `/api/meetings/${meeting_id}`;
      const audioEndpoint = API_ENDPOINTS?.MEETINGS?.AUDIO?.(meeting_id) || `/api/meetings/${meeting_id}/audio`;
      const transcriptEndpoint = API_ENDPOINTS?.MEETINGS?.TRANSCRIPT?.(meeting_id) || `/api/meetings/${meeting_id}/transcript`;
      
      const response = await apiClient.get(`${baseUrl}${detailEndpoint}`);
      setMeeting(response.data);

      // 设置访问密码状态
      if (response.data.access_password) {
        setAccessPassword(response.data.access_password);
        setPasswordEnabled(true);
      } else {
        setAccessPassword(null);
        setPasswordEnabled(false);
      }

      // Handle transcription status from meeting details
      if (response.data.transcription_status) {
        const newStatus = response.data.transcription_status;
        setTranscriptionStatus(newStatus);
        setTranscriptionProgress(newStatus.progress || 0);
        
        // If transcription is in progress, start polling for updates
        // 但只有当前没有在轮询时才启动新的轮询
        if (['pending', 'processing'].includes(newStatus.status)) {
          if (!statusCheckInterval) {
            console.log('转录进行中，开始轮询状态');
            startStatusPolling(newStatus.task_id);
          }
        } else {
          // 如果转录已完成，确保清除任何现有的轮询
          console.log('转录已完成或失败，状态:', newStatus.status);
          if (statusCheckInterval) {
            clearInterval(statusCheckInterval);
            setStatusCheckInterval(null);
          }
        }
      } else {
        setTranscriptionStatus(null);
        setTranscriptionProgress(0);
        // 清除轮询
        if (statusCheckInterval) {
          clearInterval(statusCheckInterval);
          setStatusCheckInterval(null);
        }
      }
      
      // Fetch audio file if available
      try {
        const audioResponse = await apiClient.get(`${baseUrl}${audioEndpoint}`);
        // Use streaming API endpoint for Safari compatibility (supports HTTP Range requests)
        setAudioUrl(`${baseUrl}/api/meetings/${meeting_id}/audio/stream`);
        setAudioFileName(audioResponse.data.file_name);

        // 重置音频状态（新会议的音频）
        setIsPlaying(false);
        setCurrentTime(0);
        setDuration(0);
        setAudioLoading(true);
        setAudioCanPlay(false);
        setAudioBuffering(false);
        setAudioError(null);
        setCurrentSubtitle('');
        setCurrentSpeaker('');
        setCurrentHighlightIndex(-1);
      } catch (audioError) {
        console.warn('No audio file available:', audioError);
        setAudioUrl(null);
        setAudioFileName(null);

        // 重置音频状态（无音频）
        setIsPlaying(false);
        setCurrentTime(0);
        setDuration(0);
        setAudioLoading(false);
        setAudioCanPlay(false);
        setAudioBuffering(false);
        setAudioError(null);
        setCurrentSubtitle('');
        setCurrentSpeaker('');
        setCurrentHighlightIndex(-1);
      }
      
      // Fetch transcript segments from database
      try {
        const transcriptResponse = await apiClient.get(`${baseUrl}${transcriptEndpoint}`);
        setTranscript(transcriptResponse.data);
        
        console.log('First transcript item:', transcriptResponse.data[0]);
        
        // 现在使用speaker_id字段进行分组
        const allSpeakerIds = transcriptResponse.data
          .map(item => item.speaker_id)
          .filter(speakerId => speakerId !== null && speakerId !== undefined);
        
        console.log('Extracted speaker IDs:', allSpeakerIds);
        
        const uniqueSpeakers = [...new Set(allSpeakerIds)]
          .map(speakerId => {
            const segment = transcriptResponse.data.find(item => item.speaker_id === speakerId);
            return {
              speaker_id: speakerId,
              speaker_tag: segment ? (segment.speaker_tag || `发言人 ${speakerId}`) : `发言人 ${speakerId}`
            };
          })
          .sort((a, b) => a.speaker_id - b.speaker_id); // 按speaker_id数值排序
        
        console.log('Final unique speakers:', uniqueSpeakers);
        setSpeakerList(uniqueSpeakers);
        
        // 初始化编辑状态
        const initialEditingState = {};
        uniqueSpeakers.forEach(speaker => {
          initialEditingState[speaker.speaker_id] = speaker.speaker_tag;
        });
        setEditingSpeakers(initialEditingState);
        
      } catch (transcriptError) {
        console.warn('No transcript data available:', transcriptError);
        setTranscript([]);
        setSpeakerList([]);
      }
    } catch (err) {
      console.error('Error fetching meeting details:', err);
      setError('无法加载会议详情，请稍后重试。');
    } finally {
      setLoading(false);
    }
  };

  const loadFileSizeConfig = async () => {
    try {
      const fileSize = await configService.getMaxFileSize();
      setMaxFileSize(fileSize);
    } catch (error) {
      console.warn('Failed to load file size config:', error);
    }
  };

  // 获取会议总结模板列表
  const fetchPromptList = async () => {
    try {
      const response = await apiClient.get(buildApiUrl(API_ENDPOINTS.PROMPTS.ACTIVE('MEETING_TASK')));
      const prompts = response.data.prompts || [];  // 修正：从 data.prompts 取值
      setPromptList(prompts);

      // 设置默认选中的模板（默认模板或第一个）
      const defaultPrompt = prompts.find(p => p.is_default) || prompts[0];
      if (defaultPrompt) {
        setSelectedPromptId(defaultPrompt.id);
      }
    } catch (error) {
      console.warn('Failed to load prompt list:', error);
      setPromptList([]);
    }
  };

  // 获取导航信息（上一条/下一条会议）
  const fetchNavigationInfo = async () => {
    try {
      const params = {
        user_id: user.user_id,
        filter_type: filterContext.filterType,
        search: filterContext.searchQuery || undefined,
        tags: filterContext.selectedTags.length > 0 ? filterContext.selectedTags.join(',') : undefined
      };

      const response = await apiClient.get(
        buildApiUrl(API_ENDPOINTS.MEETINGS.NAVIGATION(meeting_id)),
        { params }
      );

      setNavigationInfo(response.data);
    } catch (err) {
      console.error('Error fetching navigation info:', err);
      // 不显示错误提示，静默失败
    }
  };

  // 当会议详情加载完成后，获取导航信息
  useEffect(() => {
    if (meeting && user && filterContext) {
      fetchNavigationInfo();
    }
  }, [meeting, user, filterContext, meeting_id]);

  const handleFileChange = (e) => {
    const file = e.target.files[0];
    if (file) {
      // Check file type
      const allowedMimeTypes = ['audio/mp3', 'audio/wav', 'audio/m4a', 'audio/mpeg', 'audio/mp4', 'audio/x-m4a'];
      const fileExtension = file.name.toLowerCase().split('.').pop();
      const allowedExtensions = ['mp3', 'wav', 'm4a', 'mpeg'];

      if (!allowedMimeTypes.includes(file.type) && !allowedExtensions.includes(fileExtension)) {
        setUploadError('请上传支持的音频格式 (MP3, WAV, M4A)');
        showToast('请上传支持的音频格式 (MP3, WAV, M4A)', 'error');
        return;
      }
      // Check file size
      if (file.size > maxFileSize) {
        const maxSizeMB = Math.round(maxFileSize / (1024 * 1024));
        setUploadError(`音频文件大小不能超过${maxSizeMB}MB`);
        showToast(`音频文件大小不能超过${maxSizeMB}MB`, 'error');
        return;
      }
      setAudioFile(file);
      setUploadError('');
      setShowUploadConfirm(true);
    }
  };

  const handleUploadAudio = async () => {
    if (!audioFile) {
      setUploadError('请先选择音频文件');
      showToast('请先选择音频文件', 'error');
      return;
    }

    setIsUploading(true);
    setUploadError('');

    try {
      const formDataUpload = new FormData();
      formDataUpload.append('audio_file', audioFile);
      formDataUpload.append('meeting_id', meeting_id);
      formDataUpload.append('force_replace', 'true');
      formDataUpload.append('auto_summarize', 'false');

      const response = await apiClient.post(buildApiUrl(API_ENDPOINTS.MEETINGS.UPLOAD_AUDIO), formDataUpload, {
        headers: {
          'Content-Type': 'multipart/form-data',
        },
      });

      // 上传成功后，刷新整个会议详情数据
      await fetchMeetingDetails();

      // 清理上传状态
      setAudioFile(null);
      setShowUploadConfirm(false);

      // Reset file input
      const fileInput = document.getElementById('audio-file-upload');
      if (fileInput) fileInput.value = '';

      showToast('音频上传成功，正在进行智能转录...', 'success');

    } catch (err) {
      console.error('Upload error:', err);
      setUploadError(err.response?.data?.message || '上传音频文件失败，请重试');
      showToast(err.response?.data?.message || '上传音频文件失败，请重试', 'error');
    } finally {
      setIsUploading(false);
    }
  };

  const handleStartTranscription = async () => {
    try {
      if (!audioUrl) {
        showToast('没有可用的音频文件', 'error');
        return;
      }

      if (transcriptionStatus && ['pending', 'processing'].includes(transcriptionStatus.status)) {
        showToast('转录任务正在进行中', 'info');
        return;
      }

      // 调用后端API启动转录
      const response = await apiClient.post(buildApiUrl(`/api/meetings/${meeting_id}/transcription/start`));

      // response 是 {code, message, data}，task_id 在 data 中
      if (response.data && response.data.task_id) {
        // 立即更新本地状态为新任务的pending状态
        const newStatus = {
          task_id: response.data.task_id,
          status: 'pending',
          progress: 0,
          meeting_id: parseInt(meeting_id)
        };
        setTranscriptionStatus(newStatus);
        setTranscriptionProgress(0);

        // 清空现有的转录数据和会议摘要（因为后端已经删除了）
        setTranscript([]);
        setSpeakerList([]);
        setMeeting(prevMeeting => ({
          ...prevMeeting,
          summary: null
        }));

        showToast('智能转录已启动', 'success');
        // 开始轮询转录状态
        startStatusPolling(response.data.task_id);
      } else {
        showToast('启动转录成功，但未获取到任务ID', 'warning');
      }

    } catch (err) {
      console.error('Start transcription error:', err);
      showToast(err.response?.data?.message || err.message || '启动转录失败，请重试', 'error');
    }
  };





  const handlePlayPause = () => {
    if (audioRef.current) {
      // 如果音频还未加载完成，不允许播放
      if (!audioCanPlay && !isPlaying) {
        showToast('音频正在加载中，请稍候...', 'info');
        return;
      }

      if (isPlaying) {
        audioRef.current.pause();
      } else {
        audioRef.current.play().catch(err => {
          console.error('播放失败:', err);
          showToast('播放失败，请重试', 'error');
        });
      }
      setIsPlaying(!isPlaying);
    }
  };

  const handleTimeUpdate = () => {
    if (audioRef.current) {
      const currentTime = audioRef.current.currentTime;
      setCurrentTime(currentTime);
      
      // 更新字幕显示
      updateSubtitle(currentTime);
    }
  };
  
  const updateSubtitle = (currentTime) => {
    const currentTimeMs = currentTime * 1000;
    const currentSegment = transcript.find(item => 
      currentTimeMs >= item.start_time_ms && currentTimeMs <= item.end_time_ms
    );
    
    if (currentSegment) {
      setCurrentSubtitle(currentSegment.text_content);
      // 确保使用 speaker_tag 来保持一致性
      setCurrentSpeaker(currentSegment.speaker_tag || `发言人 ${currentSegment.speaker_id}`);
      
      // 找到当前segment在transcript数组中的索引
      const currentIndex = transcript.findIndex(item => item.segment_id === currentSegment.segment_id);
      setCurrentHighlightIndex(currentIndex);
      
      // 滚动到对应的转录条目（仅在启用自动滚动时）
      if (autoScrollEnabled && currentIndex !== -1 && transcriptRefs.current[currentIndex]) {
        transcriptRefs.current[currentIndex].scrollIntoView({
          behavior: 'smooth',
          block: 'center'
        });
      }
    } else {
      setCurrentSubtitle('');
      setCurrentSpeaker('');
      setCurrentHighlightIndex(-1);
    }
  };

  const handleLoadedMetadata = () => {
    if (audioRef.current) {
      setDuration(audioRef.current.duration);
      // Safari在preload="metadata"模式下可能不触发onCanPlay，所以这里也更新状态
      setAudioLoading(false);
      setAudioCanPlay(true);
      setAudioError(null);
    }
  };

  // 音频可以开始播放
  const handleCanPlay = () => {
    setAudioLoading(false);
    setAudioCanPlay(true);
    setAudioError(null);
  };

  // 音频可以完整播放（不需要再缓冲）
  const handleCanPlayThrough = () => {
    setAudioLoading(false);
    setAudioBuffering(false);
  };

  // 音频开始加载
  const handleLoadStart = () => {
    setAudioLoading(true);
    setAudioCanPlay(false);
    setAudioError(null);
  };

  // 音频因缓冲而等待
  const handleWaiting = () => {
    setAudioBuffering(true);
  };

  // 音频开始播放（缓冲结束）
  const handlePlaying = () => {
    setAudioBuffering(false);
  };

  // 音频加载错误
  const handleAudioError = (e) => {
    setAudioLoading(false);
    setAudioCanPlay(false);
    const error = e.target?.error;
    let errorMessage = '音频加载失败';
    if (error) {
      switch (error.code) {
        case 1:
          errorMessage = '音频加载被中止';
          break;
        case 2:
          errorMessage = '网络错误，无法加载音频';
          break;
        case 3:
          errorMessage = '音频解码失败';
          break;
        case 4:
          errorMessage = '不支持的音频格式';
          break;
        default:
          errorMessage = '音频加载失败';
      }
    }
    setAudioError(errorMessage);
    showToast(errorMessage, 'error');
  };

  // 音频播放结束
  const handleEnded = () => {
    setIsPlaying(false);
  };

  const handleSeek = (e, progressElement) => {
    if (!audioRef.current || !duration) return;

    // 使用传入的元素或 currentTarget
    const element = progressElement || e.currentTarget;
    const rect = element.getBoundingClientRect();
    const percent = Math.max(0, Math.min(1, (e.clientX - rect.left) / rect.width));
    const seekTime = percent * duration;

    audioRef.current.currentTime = seekTime;
    setCurrentTime(seekTime);
  };

  const handleProgressMouseDown = (e) => {
    e.preventDefault();
    const progressElement = e.currentTarget; // 保存进度条元素引用

    const handleMouseMove = (moveEvent) => {
      handleSeek(moveEvent, progressElement);
    };

    const handleMouseUp = () => {
      document.removeEventListener('mousemove', handleMouseMove);
      document.removeEventListener('mouseup', handleMouseUp);
    };

    document.addEventListener('mousemove', handleMouseMove);
    document.addEventListener('mouseup', handleMouseUp);

    handleSeek(e, progressElement);
  };

  const handleVolumeChange = (e) => {
    const newVolume = parseFloat(e.target.value);
    setVolume(newVolume);
    if (audioRef.current) {
      audioRef.current.volume = newVolume;
    }
  };

  const jumpToTime = (timestamp) => {
    if (audioRef.current) {
      audioRef.current.currentTime = timestamp;
      setCurrentTime(timestamp);
      audioRef.current.play();
      setIsPlaying(true);
    }
  };

  const handleDeleteMeeting = async () => {
    try {
      await apiClient.delete(buildApiUrl(API_ENDPOINTS.MEETINGS.DELETE(meeting_id)));
      navigate('/dashboard');
    } catch (err) {
      console.error('Error deleting meeting:', err);
      setError(err.response?.data?.message || '删除会议失败，请重试');
    }
  };

  const handleSpeakerTagUpdate = async (speakerId, newTag) => {
    try {
      const baseUrl = "";
      await apiClient.put(`${baseUrl}/api/meetings/${meeting_id}/speaker-tags`, {
        speaker_id: speakerId,
        new_tag: newTag
      });
      
      // 更新本地状态
      setTranscript(prev => prev.map(item => 
        item.speaker_id === speakerId 
          ? { ...item, speaker_tag: newTag }
          : item
      ));
      
      setSpeakerList(prev => prev.map(speaker => 
        speaker.speaker_id === speakerId
          ? { ...speaker, speaker_tag: newTag }
          : speaker
      ));
      
    } catch (err) {
      console.error('Error updating speaker tag:', err);
      setError(err.response?.data?.message || '更新发言人标签失败，请重试');
    }
  };
  
  const handleBatchSpeakerUpdate = async () => {
    try {
      const baseUrl = "";
      const updates = Object.entries(editingSpeakers).map(([speakerId, newTag]) => ({
        speaker_id: parseInt(speakerId), // 确保传递整数类型
        new_tag: newTag
      }));
      
      await apiClient.put(`${baseUrl}/api/meetings/${meeting_id}/speaker-tags/batch`, {
        updates: updates
      });
      
      // 更新本地状态
      setTranscript(prev => prev.map(item => {
        const newTag = editingSpeakers[item.speaker_id];
        return newTag ? { ...item, speaker_tag: newTag } : item;
      }));
      
      setSpeakerList(prev => prev.map(speaker => ({
        ...speaker,
        speaker_tag: editingSpeakers[speaker.speaker_id] || speaker.speaker_tag
      })));
      
      setShowSpeakerEdit(false);
      
    } catch (err) {
      console.error('Error batch updating speaker tags:', err);
      setError(err.response?.data?.message || '批量更新发言人标签失败，请重试');
    }
  };
  
  const handleEditingSpeakerChange = (speakerId, newTag) => {
    setEditingSpeakers(prev => ({
      ...prev,
      [speakerId]: newTag
    }));
  };
  
  const handleSpeakerEditOpen = () => {
    console.log('Opening speaker edit modal');
    console.log('Current transcript:', transcript);
    console.log('Current speakerList:', speakerList);
    console.log('Current editingSpeakers:', editingSpeakers);
    setShowSpeakerEdit(true);
  };
  
  const handleTranscriptEdit = (index) => {
    setEditingTranscriptIndex(index);
    
    // 获取前一条、当前条、后一条的数据
    const editItems = [];
    if (index > 0) editItems.push({ ...transcript[index - 1], originalIndex: index - 1 });
    editItems.push({ ...transcript[index], originalIndex: index });
    if (index < transcript.length - 1) editItems.push({ ...transcript[index + 1], originalIndex: index + 1 });
    
    // 初始化编辑状态
    const initialEditState = {};
    editItems.forEach(item => {
      initialEditState[item.originalIndex] = item.text_content;
    });
    setEditingTranscripts(initialEditState);
    setShowTranscriptEdit(true);
  };
  
  const handleTranscriptTextChange = (index, newText) => {
    setEditingTranscripts(prev => ({
      ...prev,
      [index]: newText
    }));
  };
  
  const handleSaveTranscriptEdits = async () => {
    try {
      const baseUrl = "";
      const updates = Object.entries(editingTranscripts).map(([index, text_content]) => ({
        segment_id: transcript[index].segment_id,
        text_content: text_content
      }));
      
      await apiClient.put(`${baseUrl}/api/meetings/${meeting_id}/transcript/batch`, {
        updates: updates
      });
      
      // 更新本地状态
      setTranscript(prev => prev.map((item, idx) => {
        const newText = editingTranscripts[idx];
        return newText !== undefined ? { ...item, text_content: newText } : item;
      }));
      
      setShowTranscriptEdit(false);
      setEditingTranscripts({});
      setEditingTranscriptIndex(-1);
      
    } catch (err) {
      console.error('Error updating transcript:', err);
      setError(err.response?.data?.message || '更新转录内容失败，请重试');
    }
  };
  
  const getEditingItems = () => {
    if (editingTranscriptIndex === -1) return [];
    
    const items = [];
    const index = editingTranscriptIndex;
    
    if (index > 0) items.push({ ...transcript[index - 1], originalIndex: index - 1, position: 'prev' });
    items.push({ ...transcript[index], originalIndex: index, position: 'current' });
    if (index < transcript.length - 1) items.push({ ...transcript[index + 1], originalIndex: index + 1, position: 'next' });
    
    return items;
  };
  
  const refreshMeetingSummary = async () => {
    try {
      const baseUrl = "";
      const detailEndpoint = API_ENDPOINTS?.MEETINGS?.DETAIL?.(meeting_id) || `/api/meetings/${meeting_id}`;
      
      // 只获取会议详情中的summary字段，不显示loading
      const response = await apiClient.get(`${baseUrl}${detailEndpoint}`);
      
      // 只更新summary相关的字段，保持其他数据不变
      setMeeting(prevMeeting => ({
        ...prevMeeting,
        summary: response.data.summary
      }));
      
    } catch (error) {
      console.error('刷新会议摘要失败:', error);
    }
  };

  // AI总结相关函数 - 使用异步API
  const generateSummary = async () => {
    if (summaryLoading) return;

    setSummaryLoading(true);
    setSummaryTaskProgress(0);
    setSummaryTaskMessage('正在启动AI分析...');
    setSummaryTaskStatus('pending');

    try {
      const baseUrl = "";
      // 使用异步API，传递 prompt_id
      const response = await apiClient.post(`${baseUrl}/api/meetings/${meeting_id}/generate-summary-async`, {
        user_prompt: userPrompt,
        prompt_id: selectedPromptId
      });
      
      const taskId = response.data.task_id;
      setSummaryTaskId(taskId);
      
      // 开始轮询任务状态
      const interval = setInterval(async () => {
        try {
          const statusResponse = await apiClient.get(buildApiUrl(API_ENDPOINTS.TASKS.SUMMARY_STATUS(taskId)));
          const status = statusResponse.data;
          
          setSummaryTaskStatus(status.status);
          setSummaryTaskProgress(status.progress || 0);
          setSummaryTaskMessage(status.message || '处理中...');
          
          if (status.status === 'completed') {
            clearInterval(interval);
            setSummaryPollInterval(null);
            
            // 设置结果
            setSummaryResult({
              content: status.result,
              task_id: taskId
            });
            
            // 刷新总结历史（包含所有任务）
            await fetchSummaryHistory();
            
            // 刷新会议摘要
            await refreshMeetingSummary();
            
            setSummaryLoading(false);
            setSummaryTaskMessage('AI总结生成成功！');
            
            // 3秒后清除成功消息
            setTimeout(() => {
              setSummaryTaskMessage('');
              setSummaryTaskProgress(0);
            }, 3000);
            
          } else if (status.status === 'failed') {
            clearInterval(interval);
            setSummaryPollInterval(null);
            setSummaryLoading(false);
            setError(status.error_message || '生成AI总结失败');
            setSummaryTaskMessage('生成失败：' + (status.error_message || '未知错误'));
          }
        } catch (err) {
          console.error('Error polling task status:', err);
          // 继续轮询，不中断
        }
      }, 3000); // 每3秒查询一次
      
      setSummaryPollInterval(interval);
      
    } catch (err) {
      console.error('Error starting summary generation:', err);
      const errorMessage = err.response?.data?.message || '启动AI总结失败，请重试。';
      
      setError(errorMessage); // Set the more specific error
      setSummaryTaskMessage(`生成失败：${errorMessage}`); // Also show it in the modal
      
      setSummaryLoading(false);
      setSummaryTaskProgress(0);
    }
  };
  
  const fetchSummaryHistory = async () => {
    try {
      const baseUrl = "";
      // 获取所有LLM任务历史（包含进度和状态）
      const tasksResponse = await apiClient.get(`${baseUrl}/api/meetings/${meeting_id}/llm-tasks`);
      const tasks = tasksResponse.data.tasks || [];
      
      // 转换为历史记录格式，包含任务信息
      const summaries = tasks
        .filter(task => task.status === 'completed' && task.result)
        .map(task => ({
          id: task.task_id,
          content: task.result,
          user_prompt: task.user_prompt,
          created_at: task.created_at,
          task_info: {
            task_id: task.task_id,
            status: task.status,
            progress: task.progress
          }
        }));
      
      setSummaryHistory(summaries);
      
      // 如果有进行中的任务，恢复轮询
      const runningTask = tasks.find(task => ['pending', 'processing'].includes(task.status));
      if (runningTask && !summaryPollInterval) {
        setSummaryTaskId(runningTask.task_id);
        setSummaryTaskStatus(runningTask.status);
        setSummaryTaskProgress(runningTask.progress || 0);
        setSummaryLoading(true);
        
        // 恢复轮询
        const interval = setInterval(async () => {
          try {
            const statusResponse = await apiClient.get(buildApiUrl(API_ENDPOINTS.TASKS.SUMMARY_STATUS(runningTask.task_id)));
            const status = statusResponse.data;
            
            setSummaryTaskStatus(status.status);
            setSummaryTaskProgress(status.progress || 0);
            setSummaryTaskMessage(status.message || '处理中...');
            
            if (['completed', 'failed'].includes(status.status)) {
              clearInterval(interval);
              setSummaryPollInterval(null);
              setSummaryLoading(false);
              
              if (status.status === 'completed') {
                await fetchSummaryHistory();
                await refreshMeetingSummary();
              }
            }
          } catch (err) {
            console.error('Error polling task status:', err);
          }
        }, 3000);
        
        setSummaryPollInterval(interval);
      }
      
    } catch (err) {
      console.error('Error fetching summary history:', err);
      setSummaryHistory([]);
    }
  };
  
  const openSummaryModal = async () => {
    // Frontend check before opening the modal
    if (!transcriptionStatus || transcriptionStatus.status !== 'completed') {
      showToast('会议转录尚未完成或处理失败，请在转录成功后再生成AI总结。', 'warning');
      return; // Prevent modal from opening
    }

    setShowSummaryModal(true);
    setUserPrompt('');
    setSummaryResult(null);
    await fetchSummaryHistory();
  };

  const closeSummaryModal = async () => {
    setShowSummaryModal(false);
    // 关闭弹窗时只刷新摘要部分，避免整页刷新
    if (summaryResult) {
      await refreshMeetingSummary();
    }
  };

  // 导出会议总结为图片
  const exportSummaryToImage = async () => {
    try {
      if (!meeting?.summary) {
        showToast('暂无会议总结内容，请先生成AI总结。', 'warning');
        return;
      }

      const meetingTime = tools.formatDateTime(meeting.meeting_time);
      const attendeesList = meeting.attendees.map(attendee =>
        typeof attendee === 'string' ? attendee : attendee.caption
      ).join('、');

      await exportService.exportMeetingSummaryToImage({
        title: meeting.title || '会议总结',
        summary: meeting.summary,
        metadata: {
          meetingTime,
          creator: meeting.creator_username,
          attendeeCount: meeting.attendees.length,
          attendees: attendeesList
        }
      });

      showToast('总结已成功导出为图片', 'success');
    } catch (error) {
      console.error('图片导出失败:', error);
      showToast('图片导出失败，请重试。', 'error');
    }
  };

  // 导出思维导图为图片
  const exportMindMapToImage = async () => {
    try {
      if (!meeting?.summary) {
        showToast('暂无内容，无法导出思维导图。', 'warning');
        return;
      }

      await exportService.exportMindMapToImage({
        title: meeting.title || '会议'
      });

      showToast('思维导图已成功导出为图片', 'success');
    } catch (error) {
      console.error('思维导图导出失败:', error);
      showToast(error.message || '思维导图导出失败，请重试。', 'error');
    }
  };

  // 访问密码管理函数
  const generatePassword = () => {
    // 生成4位混合密码（数字+字母）
    const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789';
    let password = '';
    for (let i = 0; i < 4; i++) {
      password += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return password;
  };

  const handleTogglePassword = async () => {
    try {
      setPasswordLoading(true);

      if (passwordEnabled) {
        // 关闭密码
        await apiClient.put(buildApiUrl(`/api/meetings/${meeting_id}/access-password`), {
          password: null
        });
        setAccessPassword(null);
        setPasswordEnabled(false);
        setShowPassword(false);
        showToast('访问密码已关闭', 'success');
      } else {
        // 生成并开启密码
        const newPassword = generatePassword();
        await apiClient.put(buildApiUrl(`/api/meetings/${meeting_id}/access-password`), {
          password: newPassword
        });
        setAccessPassword(newPassword);
        setPasswordEnabled(true);
        setShowPassword(true);
        showToast('访问密码已生成', 'success');
      }
    } catch (err) {
      console.error('密码操作失败:', err);
      showToast(err.response?.data?.message || '密码操作失败，请重试', 'error');
    } finally {
      setPasswordLoading(false);
    }
  };

  const handleCopyPassword = () => {
    if (accessPassword) {
      navigator.clipboard.writeText(accessPassword);
      setPasswordCopied(true);
      showToast('密码已复制到剪贴板', 'success');
      setTimeout(() => setPasswordCopied(false), 2000);
    }
  };

  const isCreator = meeting && user && String(meeting.creator_id) === String(user.user_id);

  if (loading) {
    return <PageLoading message="加载中..." />;
  }

  if (error) {
    return <div className="error-container"><p>{error}</p><Link to="/dashboard"><span className="btn-secondary">返回首页</span></Link></div>;
  }

  if (!meeting) {
    return <div className="error-container"><p>未找到会议信息。</p><Link to="/dashboard"><span className="btn-secondary">返回首页</span></Link></div>;
  }

  return (
    <div className="meeting-details-page">
      <div className="details-header">
        <div className="header-left">
          {/* 融合导航栏：返回首页 + 上一条/下一条 */}
          <div className="unified-navigation">
            <Link to="/dashboard" className="nav-btn back-home-btn">
              <ArrowLeft size={18} />
              <span>返回首页</span>
            </Link>

            {navigationInfo.total_count !== null && navigationInfo.total_count > 0 && (
              <>
                <Link
                  to={navigationInfo.prev_meeting_id ? `/meetings/${navigationInfo.prev_meeting_id}` : '#'}
                  state={{ filterContext }}
                  className={`nav-btn prev-btn ${!navigationInfo.prev_meeting_id ? 'disabled' : ''}`}
                  onClick={(e) => !navigationInfo.prev_meeting_id && e.preventDefault()}
                >
                  <ChevronLeft size={18} />
                  <span>上一条</span>
                </Link>

                {navigationInfo.current_index !== null && (
                  <span className="nav-position">
                    {navigationInfo.current_index + 1} / {navigationInfo.total_count}
                  </span>
                )}

                <Link
                  to={navigationInfo.next_meeting_id ? `/meetings/${navigationInfo.next_meeting_id}` : '#'}
                  state={{ filterContext }}
                  className={`nav-btn next-btn ${!navigationInfo.next_meeting_id ? 'disabled' : ''}`}
                  onClick={(e) => !navigationInfo.next_meeting_id && e.preventDefault()}
                >
                  <span>下一条</span>
                  <ChevronRight size={18} />
                </Link>
              </>
            )}
          </div>
        </div>

        {isCreator && (
          <div className="meeting-actions">
            <Link to={`/meetings/edit/${meeting_id}`} className="action-btn icon-only edit-btn" title="编辑会议">
              <Edit size={16} />
            </Link>
            <button
              className="action-btn icon-only delete-btn"
              onClick={() => setDeleteConfirmInfo({ id: meeting_id, title: meeting.title })}
              title="删除会议"
            >
              <Trash2 size={16} />
            </button>
            <button
              className="action-btn icon-only qr-btn"
              onClick={() => setShowQRModal(true)}
              title="分享会议二维码"
            >
              <QrCode size={16} />
            </button>
          </div>
        )}
      </div>
      
      <div className="details-layout">
        <div className="main-content">
          <div className="details-content-card">
            <header className="detail-card-header">
              <div className="meeting-header-title">
                <h1>
                  {meeting.title}
                  {meeting.tags && meeting.tags.length > 0 && (
                    <TagDisplay
                      tags={meeting.tags.map(tag => tag.name)}
                      size="medium"
                      showIcon={true}
                      className="inline-title-tags"
                    />
                  )}
                </h1>
              </div>
              <div className="meta-grid">
                <div className="meta-item">
                  <Calendar size={18} />
                  <strong>日期:</strong>
                  <span>{tools.formatDateTime(meeting.meeting_time).split(' ')[0].slice(2)}</span>
                </div>
                <div className="meta-item">
                  <Clock size={18} />
                  <strong>时间:</strong>
                  <span>{tools.formatDateTime(meeting.meeting_time).split(' ')[1]}</span>
                </div>
                <div className="meta-item">
                  <User size={18} />
                  <strong>创建人:</strong>
                  <span>{meeting.creator_username}</span>
                </div>
                <div className="meta-item meta-item-password">
                  <Lock size={18} />
                  <strong>访问密码:</strong>
                  {isCreator ? (
                    // 创建人：显示开启/关闭按钮
                    <div className="password-control-inline">
                      <button
                        className={`password-toggle-inline ${passwordEnabled ? 'enabled' : 'disabled'}`}
                        onClick={handleTogglePassword}
                        disabled={passwordLoading}
                        title={passwordEnabled ? '点击关闭密码' : '点击开启密码'}
                      >
                        {passwordLoading ? (
                          <Loader size={14} className="spin" />
                        ) : passwordEnabled ? (
                          <>
                            <span className="password-text">{showPassword ? accessPassword : '••••'}</span>
                          </>
                        ) : (
                          <>
                            <span>开启</span>
                          </>
                        )}
                      </button>
                      {passwordEnabled && accessPassword && (
                        <button
                          className="password-icon-btn"
                          onClick={() => setShowPassword(!showPassword)}
                          title={showPassword ? '隐藏密码' : '显示密码'}
                        >
                          {showPassword ? <EyeOff size={14} /> : <Eye size={14} />}
                        </button>
                      )}
                    </div>
                  ) : (
                    // 非创建人：显示密码或"未设置"
                    passwordEnabled && accessPassword ? (
                      <div className="password-view-inline">
                        <span className="password-text">{showPassword ? accessPassword : '••••'}</span>
                        <button
                          className="password-icon-btn"
                          onClick={() => setShowPassword(!showPassword)}
                          title={showPassword ? '隐藏密码' : '显示密码'}
                        >
                          {showPassword ? <EyeOff size={14} /> : <Eye size={14} />}
                        </button>
                      </div>
                    ) : (
                      <span className="no-password-text">未设置</span>
                    )
                  )}
                </div>
                <div className="meta-item meta-item-attendees">
                  <Users size={18} />
                  <strong>参会人员<span className="attendee-count">（{meeting.attendees.length}人）</span>:</strong>
                  <span className="attendees-inline">
                    {meeting.attendees.map((attendee, index) => (
                      <span key={index} className="attendee-name">
                        {typeof attendee === 'string' ? attendee : attendee.caption}
                        {index < meeting.attendees.length - 1 && '、'}
                      </span>
                    ))}
                  </span>
                </div>
              </div>
            </header>

            {/* Audio Player Section */}
            <section className="card-section audio-section">
              <div className="section-header-with-menu">
                <h2><Volume2 size={20} /> 会议录音</h2>
                {meeting?.creator_id === user?.user_id && (
                  <Dropdown
                    trigger={
                      <button className="audio-menu-button" title="音频操作">
                        <MoreVertical size={20} />
                      </button>
                    }
                    items={[
                      {
                        label: '音频上传',
                        icon: <Upload size={16} />,
                        onClick: () => document.getElementById('audio-file-upload').click()
                      },
                      ...(audioUrl ? [{
                        label: '智能转录',
                        icon: <Brain size={16} />,
                        onClick: handleStartTranscription,
                        disabled: transcriptionStatus && ['pending', 'processing'].includes(transcriptionStatus.status)
                      }] : [])
                    ]}
                    align="right"
                  />
                )}
                <input
                  type="file"
                  id="audio-file-upload"
                  accept="audio/*"
                  onChange={handleFileChange}
                  style={{ display: 'none' }}
                />
              </div>
              {audioUrl ? (
                <div className="audio-player">
                  {audioFileName && (
                    <div className="audio-file-info">
                      <span className="audio-file-name">{audioFileName}</span>
                      {audioLoading && (
                        <span className="audio-loading-hint">
                          <Loader size={14} className="spin" />
                          加载中...
                        </span>
                      )}
                      {audioError && (
                        <span className="audio-error-hint">{audioError}</span>
                      )}
                    </div>
                  )}
                  <audio
                    key={audioUrl || 'no-audio'} // 使用audioUrl作为key，确保切换会议时重新创建audio元素
                    ref={audioRef}
                    src={audioUrl}
                    onTimeUpdate={handleTimeUpdate}
                    onLoadedMetadata={handleLoadedMetadata}
                    onCanPlay={handleCanPlay}
                    onCanPlayThrough={handleCanPlayThrough}
                    onLoadStart={handleLoadStart}
                    onWaiting={handleWaiting}
                    onPlaying={handlePlaying}
                    onError={handleAudioError}
                    onEnded={handleEnded}
                    preload="metadata"
                  />
                  
                  {/* 转录状态显示 */}
                  {transcriptionStatus && (
                    <div className="transcription-status">
                      <div className="status-content-inline">
                        <div className="status-header-inline">
                          <Brain size={16} />
                          <span>语音转录进度：</span>
                        </div>
                        {transcriptionStatus.status === 'pending' && (
                          <div className="status-pending-inline">
                            <div className="status-indicator pending"></div>
                            <span>等待处理中...</span>
                          </div>
                        )}
                        {transcriptionStatus.status === 'processing' && (
                          <div className="status-processing-inline">
                            <div className="status-indicator processing"></div>
                            <span>转录进行中</span>
                            <div className="progress-bar-small">
                              <div 
                                className="progress-fill-small" 
                                style={{ width: `${transcriptionProgress}%` }}
                              ></div>
                            </div>
                            <span className="progress-text">{transcriptionProgress}%</span>
                          </div>
                        )}
                        {transcriptionStatus.status === 'completed' && (
                          <div className="status-completed-inline">
                            <div className="status-indicator completed"></div>
                            <span>转录已完成</span>
                            <Sparkles size={14} />
                          </div>
                        )}
                        {transcriptionStatus.status === 'failed' && (
                          <div className="status-failed-inline">
                            <div className="status-indicator failed"></div>
                            <span>转录失败</span>
                            {transcriptionStatus.error_message && (
                              <span className="error-message-inline">({transcriptionStatus.error_message})</span>
                            )}
                          </div>
                        )}
                      </div>
                    </div>
                  )}
                  
                  <div className="player-controls">
                    <button
                      className={`play-button ${audioLoading ? 'loading' : ''} ${audioBuffering ? 'buffering' : ''} ${!audioCanPlay ? 'disabled' : ''}`}
                      onClick={handlePlayPause}
                      disabled={audioLoading && !isPlaying}
                      title={audioLoading ? '音频加载中...' : (audioBuffering ? '缓冲中...' : (isPlaying ? '暂停' : '播放'))}
                    >
                      {audioLoading && !isPlaying ? (
                        <Loader size={24} className="spin" />
                      ) : audioBuffering ? (
                        <Loader size={24} className="spin" />
                      ) : isPlaying ? (
                        <Pause size={24} />
                      ) : (
                        <Play size={24} />
                      )}
                    </button>
                    
                    <div className="time-info">
                      <span>{tools.formatDuration(currentTime)}</span>
                    </div>
                    
                    <div className="progress-container" 
                         onClick={handleSeek}
                         onMouseDown={handleProgressMouseDown}>
                      <div className="progress-bar">
                        <div 
                          className="progress-fill" 
                          style={{ width: `${duration ? (currentTime / duration) * 100 : 0}%` }}
                        ></div>
                      </div>
                    </div>
                    
                    <div className="time-info">
                      <span>{tools.formatDuration(duration)}</span>
                    </div>
                    
                    <div className="volume-control">
                      <Volume2 size={18} />
                      <input
                        type="range"
                        min="0"
                        max="1"
                        step="0.1"
                        value={volume}
                        onChange={handleVolumeChange}
                        className="volume-slider"
                      />
                    </div>
                  </div>
                  
                  {/* 分割线 */}
                  <div className="audio-divider"></div>
                  
                  {/* 动态字幕显示 */}
                  <div className="subtitle-display">
                    {currentSubtitle ? (
                      <div className="subtitle-content">
                        <div className="speaker-indicator">
                          {currentSpeaker}
                        </div>
                        <div className="subtitle-text">
                          {currentSubtitle}
                        </div>
                      </div>
                    ) : (
                      <div className="subtitle-placeholder">
                        <div className="placeholder-text">播放音频时将在此处显示实时字幕</div>
                      </div>
                    )}
                  </div>
                </div>
              ) : (
                <div className="no-audio">
                  <div className="no-audio-icon">
                    <Volume2 size={48} />
                  </div>
                  <p className="no-audio-message">该会议没有录音文件</p>
                  <p className="no-audio-hint">录音功能可能未开启或录音文件丢失</p>
                </div>
              )}
            </section>

            {/* Upload Confirmation Modal */}
            {showUploadConfirm && (
              <div className="delete-modal-overlay" onClick={() => setShowUploadConfirm(false)}>
                <div className="delete-modal" onClick={(e) => e.stopPropagation()}>
                  <h3>确认上传音频</h3>
                  <p>重新上传音频文件将清空已有的会话转录，是否继续？</p>
                  {audioFile && (
                    <div className="selected-file-info">
                      <span>已选择: {audioFile.name}</span>
                      <span className="file-size">
                        ({(audioFile.size / (1024 * 1024)).toFixed(2)} MB)
                      </span>
                    </div>
                  )}
                  {uploadError && (
                    <div className="error-message">{uploadError}</div>
                  )}
                  <div className="modal-actions">
                    <button
                      className="btn-cancel"
                      onClick={() => {
                        setShowUploadConfirm(false);
                        setAudioFile(null);
                        const fileInput = document.getElementById('audio-file-upload');
                        if (fileInput) fileInput.value = '';
                      }}
                    >
                      取消
                    </button>
                    <button
                      className="btn-submit"
                      onClick={handleUploadAudio}
                      disabled={isUploading}
                    >
                      {isUploading ? '上传中...' : '确定上传'}
                    </button>
                  </div>
                </div>
              </div>
            )}

            <section className="card-section summary-tabs-section">
              <ContentViewer
                content={meeting.summary}
                title={meeting.title}
                emptyMessage="暂无会议总结"
                summaryActions={
                  meeting.summary && (
                    <button
                      className="action-btn export-btn"
                      onClick={exportSummaryToImage}
                      title="导出图片"
                    >
                      <Image size={16} />
                      <span>导出图片</span>
                    </button>
                  )
                }
                mindmapActions={
                  meeting.summary && (
                    <button
                      className="action-btn export-btn"
                      onClick={exportMindMapToImage}
                      title="导出图片"
                    >
                      <Image size={16} />
                      <span>导出图片</span>
                    </button>
                  )
                }
              />
            </section>
          </div>
        </div>

        {/* Transcript Sidebar */}
        <div className="transcript-sidebar">
          <div className="transcript-header">
            <h3>
              <MessageCircle size={20} /> 
              对话转录
              <span 
                className="sync-scroll-icon"
                onClick={() => setAutoScrollEnabled(!autoScrollEnabled)}
                title={autoScrollEnabled ? "关闭同步滚动" : "开启同步滚动"}
              >
                {autoScrollEnabled ? <RefreshCw size={16} /> : <RefreshCwOff size={16} />}
              </span>
            </h3>
            <div className="transcript-controls">
              {isCreator && (
                <>
                  <button 
                    className="edit-speakers-btn"
                    onClick={handleSpeakerEditOpen}
                    title="编辑发言人标签"
                  >
                    <Settings size={16} />
                    <span>编辑标签</span>
                  </button>
                  <button 
                    className="ai-summary-btn"
                    onClick={openSummaryModal}
                    title="AI总结"
                  >
                    <Brain size={16} />
                    <span>AI总结</span>
                  </button>
                </>
              )}
            </div>
          </div>
          
          <div className="transcript-content">
            {transcript.map((item, index) => {
              // 计算当前发言人的序号：这是该发言人的第几条发言
              const speakerSegments = transcript.filter(seg => seg.speaker_id === item.speaker_id);
              const currentSpeakerIndex = speakerSegments.findIndex(seg => seg.segment_id === item.segment_id) + 1;
              const totalSpeakerSegments = speakerSegments.length;

              return (
                <div
                  key={item.segment_id}
                  ref={(el) => transcriptRefs.current[index] = el}
                  className={`transcript-item ${currentHighlightIndex === index ? 'active' : ''}`}
                >
                  <div className="transcript-header-item">
                    <span
                      className="speaker-name clickable"
                      onClick={() => jumpToTime(item.start_time_ms / 1000)}
                      title="跳转到此时间点播放"
                    >
                      {item.speaker_tag}
                      <span className="speaker-index"> {currentSpeakerIndex}/{totalSpeakerSegments}</span>
                    </span>
                    <div className="transcript-item-actions">
                      <span 
                        className="timestamp clickable"
                        onClick={() => jumpToTime(item.start_time_ms / 1000)}
                        title="跳转到此时间点播放"
                      >
                        {tools.formatDuration(item.start_time_ms / 1000)}
                      </span>
                      {isCreator && (
                        <button
                          className="edit-transcript-btn"
                          onClick={() => handleTranscriptEdit(index)}
                          title="编辑转录内容"
                        >
                          <Edit3 size={14} />
                        </button>
                      )}
                    </div>
                  </div>
                  <div
                    className="transcript-text clickable"
                    onClick={() => jumpToTime(item.start_time_ms / 1000)}
                    title="跳转到此时间点播放"
                  >
                    {item.text_content}
                  </div>
                </div>
              );
            })}
            </div>
        </div>
      </div>

      {/* Delete Confirmation Dialog */}
      <ConfirmDialog
        isOpen={!!deleteConfirmInfo}
        onClose={() => setDeleteConfirmInfo(null)}
        onConfirm={handleDeleteMeeting}
        title="删除会议"
        message={`确定要删除会议"${deleteConfirmInfo?.title}"吗？此操作无法撤销。`}
        confirmText="确定删除"
        cancelText="取消"
        type="danger"
      />

      {/* Speaker Tags Edit Modal */}
      {showSpeakerEdit && (
        <div className="speaker-edit-modal-overlay" onClick={() => setShowSpeakerEdit(false)}>
          <div className="speaker-edit-modal" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
              <h3>编辑发言人标签</h3>
              <button 
                className="close-btn"
                onClick={() => setShowSpeakerEdit(false)}
              >
                <X size={20} />
              </button>
            </div>
            
            <div className="speaker-edit-content">              
              <div className="speaker-list">
                {speakerList.length > 0 ? (
                  speakerList.map((speaker) => {
                    const segmentCount = transcript.filter(item => item.speaker_id === speaker.speaker_id).length;
                    return (
                      <div key={speaker.speaker_id} className="speaker-edit-item">
                        <div className="speaker-info">
                          <label className="speaker-id">发言人 {speaker.speaker_id}</label>
                          <span className="segment-count">({segmentCount} 条发言)</span>
                        </div>
                        <input
                          type="text"
                          value={editingSpeakers[speaker.speaker_id] || ''}
                          onChange={(e) => handleEditingSpeakerChange(speaker.speaker_id, e.target.value)}
                          className="speaker-tag-input"
                          placeholder="输入发言人姓名或标签"
                        />
                      </div>
                    );
                  })
                ) : (
                  <div className="no-speakers-message">
                    <p>暂无发言人数据，请检查转录内容是否正确加载。</p>
                  </div>
                )}
              </div>
            </div>
            
            <div className="modal-actions">
              <button 
                className="btn-cancel"
                onClick={() => setShowSpeakerEdit(false)}
              >
                取消
              </button>
              <button 
                className="btn-save"
                onClick={handleBatchSpeakerUpdate}
              >
                <Save size={16} />
                保存修改
              </button>
            </div>
          </div>
        </div>
      )}
      
      {/* Transcript Edit Modal */}
      {showTranscriptEdit && (
        <div className="transcript-edit-modal-overlay" onClick={() => setShowTranscriptEdit(false)}>
          <div className="transcript-edit-modal" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
              <h3>编辑转录内容</h3>
              <button 
                className="close-btn"
                onClick={() => setShowTranscriptEdit(false)}
              >
                <X size={20} />
              </button>
            </div>
            
            <div className="transcript-edit-content">
              <p className="modal-description">修改选中转录条目及其上下文内容：</p>
              
              <div className="transcript-edit-list">
                {getEditingItems().map((item) => (
                  <div key={item.originalIndex} className={`transcript-edit-item ${item.position}`}>
                    <div className="transcript-edit-header">
                      <span className="speaker-name">{item.speaker_tag}</span>
                      <span className="timestamp">{tools.formatDuration(item.start_time_ms / 1000)}</span>
                      {item.position === 'current' && (
                        <span className="current-indicator">当前编辑</span>
                      )}
                    </div>
                    <textarea
                      value={editingTranscripts[item.originalIndex] || item.text_content}
                      onChange={(e) => handleTranscriptTextChange(item.originalIndex, e.target.value)}
                      className="transcript-edit-textarea"
                      rows={3}
                      placeholder="输入转录内容..."
                    />
                  </div>
                ))}
              </div>
            </div>
            
            <div className="modal-actions">
              <button 
                className="btn-cancel"
                onClick={() => setShowTranscriptEdit(false)}
              >
                取消
              </button>
              <button 
                className="btn-save"
                onClick={handleSaveTranscriptEdits}
              >
                <Save size={16} />
                保存修改
              </button>
            </div>
          </div>
        </div>
      )}
      
      {/* AI Summary Modal */}
      {showSummaryModal && (
        <div className="summary-modal-overlay" onClick={closeSummaryModal}>
          <div className="summary-modal" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
              <h3><Brain size={20} /> AI总结</h3>
              <button 
                className="close-btn"
                onClick={closeSummaryModal}
              >
                <X size={20} />
              </button>
            </div>
            
            <div className="summary-modal-content">
              <div className="summary-input-section">
                <h4>生成新的总结</h4>

                {/* 模板选择器 */}
                {promptList.length > 0 && (
                  <div className="prompt-selector">
                    <label className="prompt-label">选择总结模板：</label>
                    <div className="prompt-tabs">
                      {promptList.map(prompt => (
                        <button
                          key={prompt.id}
                          className={`prompt-tab ${selectedPromptId === prompt.id ? 'active' : ''}`}
                          onClick={() => setSelectedPromptId(prompt.id)}
                          title={prompt.description}
                        >
                          {prompt.name}
                          {!!prompt.is_default && <span className="default-badge">默认</span>}
                        </button>
                      ))}
                    </div>
                  </div>
                )}

                <p className="input-description">
                  您可以添加额外的要求：
                </p>
                <textarea
                  value={userPrompt}
                  onChange={(e) => setUserPrompt(e.target.value)}
                  className="user-prompt-input"
                  placeholder="请输入您希望AI重点关注的内容，如：请重点分析决策事项和待办任务..."
                  rows={3}
                />
                <button 
                  className="generate-summary-btn"
                  onClick={generateSummary}
                  disabled={summaryLoading}
                >
                  {summaryLoading ? (
                    <>
                      <div className="loading-spinner small"></div>
                      <span>正在生成总结...</span>
                    </>
                  ) : (
                    <>
                      <Sparkles size={16} />
                      <span>生成AI总结</span>
                    </>
                  )}
                </button>
              </div>
              
              {/* 任务进度显示 */}
              {summaryLoading && (
                <div className="summary-progress-section">
                  <div className="progress-header">
                    <span className="progress-title">生成进度</span>
                    <span className="progress-percentage">{summaryTaskProgress}%</span>
                  </div>
                  <div className="progress-bar-container">
                    <div 
                      className="progress-bar-fill" 
                      style={{ width: `${summaryTaskProgress}%` }}
                    >
                      <div className="progress-bar-animate"></div>
                    </div>
                  </div>
                  {summaryTaskMessage && (
                    <div className="progress-message">
                      <div className="status-indicator processing"></div>
                      <span>{summaryTaskMessage}</span>
                    </div>
                  )}
                </div>
              )}
              
              {/* 成功消息 */}
              {!summaryLoading && summaryTaskMessage && summaryTaskStatus === 'completed' && (
                <div className="success-message">
                  <Sparkles size={16} />
                  <span>{summaryTaskMessage}</span>
                </div>
              )}
              
              {summaryResult && (
                <div className="summary-result-section">
                  <div className="summary-result-header">
                    <h4>最新生成的总结</h4>
                  </div>
                  <MarkdownRenderer
                    content={summaryResult.content}
                    className="summary-result-content"
                  />
                </div>
              )}
              
              {summaryHistory.length > 0 && (
                <div className="summary-history-section">
                  <h4>历史总结记录</h4>
                  <div className="summary-history-list">
                    {summaryHistory.map((summary, index) => (
                      <div key={summary.id} className="summary-history-item">
                        <div className="summary-history-header">
                          <span className="summary-date">
                            {new Date(summary.created_at).toLocaleString('zh-CN')}
                          </span>
                          {summary.user_prompt && (
                            <span className="user-prompt-tag">自定义要求</span>
                          )}
                        </div>
                        {summary.user_prompt && (
                          <div className="user-prompt-display">
                            <strong>用户要求：</strong>{summary.user_prompt}
                          </div>
                        )}
                        <div className="summary-content-preview">
                          {summary.content.substring(0, 200)}...
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              )}
            </div>
          </div>
        </div>
      )}

      {/* QR Code Sharing Modal */}
      <QRCodeModal
        isOpen={showQRModal}
        onClose={() => setShowQRModal(false)}
        url={`${window.location.origin}/meetings/preview/${meeting_id}`}
        title={meeting.title}
        description="扫描二维码查看会议总结"
      />

      {/* Toast notifications */}
      {toasts.map(toast => (
        <Toast
          key={toast.id}
          message={toast.message}
          type={toast.type}
          onClose={() => removeToast(toast.id)}
        />
      ))}
    </div>
  );
};

export default MeetingDetails;
