import os
import subprocess
import tempfile
import re
from typing import List, Optional
from dataclasses import dataclass


@dataclass
class SubtitleEntry:
    """字幕条目"""
    index: int
    start_time: float
    end_time: float
    text: str


class SubtitleParser:
    """SRT字幕解析器"""
    
    @classmethod
    def parse_srt(cls, content: str) -> List[SubtitleEntry]:
        """解析SRT格式字幕"""
        entries = []
        blocks = re.split(r'\n\s*\n', content.strip())
        
        for block in blocks:
            lines = block.strip().split('\n')
            if len(lines) < 3:
                continue
            
            try:
                index = int(lines[0])
                time_line = lines[1]
                
                time_match = re.match(
                    r'(\d{2}):(\d{2}):(\d{2}),(\d{3})\s*-->\s*(\d{2}):(\d{2}):(\d{2}),(\d{3})',
                    time_line
                )
                
                if time_match:
                    start_time = (
                        int(time_match.group(1)) * 3600 +
                        int(time_match.group(2)) * 60 +
                        int(time_match.group(3)) +
                        int(time_match.group(4)) / 1000.0
                    )
                    end_time = (
                        int(time_match.group(5)) * 3600 +
                        int(time_match.group(6)) * 60 +
                        int(time_match.group(7)) +
                        int(time_match.group(8)) / 1000.0
                    )
                    
                    text = ' '.join(lines[2:]).strip()
                    text = re.sub(r'<[^>]+>', '', text)
                    
                    entries.append(SubtitleEntry(
                        index=index,
                        start_time=start_time,
                        end_time=end_time,
                        text=text
                    ))
            except (ValueError, IndexError) as e:
                print(f"警告: 解析字幕块失败: {e}")
                continue
        
        return entries
    
    @classmethod
    def load_file(cls, filepath: str) -> List[SubtitleEntry]:
        """从文件加载字幕"""
        with open(filepath, 'r', encoding='utf-8') as f:
            content = f.read()
        return cls.parse_srt(content)


class VideoProcessor:
    """视频处理器"""
    
    def __init__(self, ffmpeg_path: str = "ffmpeg"):
        self.ffmpeg_path = ffmpeg_path
    
    def _run_ffmpeg(self, args: List[str]) -> bool:
        """运行ffmpeg命令"""
        cmd = [self.ffmpeg_path] + args
        try:
            subprocess.run(cmd, check=True, capture_output=True)
            return True
        except subprocess.CalledProcessError as e:
            print(f"FFmpeg错误: {e.stderr.decode('utf-8', errors='ignore') if e.stderr else '未知错误'}")
            return False
    
    def cut_video_segment(
        self,
        input_video: str,
        start_time: float,
        end_time: float,
        output_path: str
    ) -> bool:
        """剪切视频片段"""
        duration = end_time - start_time
        print(f"  剪切视频: 开始时间={start_time:.2f}, 结束时间={end_time:.2f}, 时长={duration:.2f}秒")
        args = [
            '-y',
            '-i', input_video,
            '-ss', str(start_time),
            '-t', str(duration),
            '-c:v', 'libx264',
            '-c:a', 'copy',
            '-pix_fmt', 'yuv420p',
            '-avoid_negative_ts', 'make_zero',
            output_path
        ]
        return self._run_ffmpeg(args)


class TTSGenerator:
    """TTS音频生成器"""
    
    def __init__(self):
        self.temp_dir = tempfile.mkdtemp()
    
    def generate_audio(self, text: str, output_path: str, lang: str = 'zh') -> bool:
        """生成TTS音频"""
        try:
            import edge_tts
            import asyncio
            
            async def _generate():
                if lang == 'zh':
                    voice = "zh-CN-XiaoxiaoNeural"
                elif lang == 'en':
                    voice = "en-US-JennyNeural"
                else:
                    voice = "zh-CN-XiaoxiaoNeural"
                
                rate = "-20%"
                communicate = edge_tts.Communicate(text, voice, rate=rate)
                await communicate.save(output_path)
            
            asyncio.run(_generate())
            return True
            
        except ImportError:
            print("错误: 未安装edge-tts模块。请运行: pip install edge-tts")
            return False
        except Exception as e:
            print(f"TTS生成错误: {e}")
            return False
    
    def get_audio_duration(self, audio_path: str) -> float:
        """获取音频时长"""
        try:
            from pydub import AudioSegment
            audio = AudioSegment.from_file(audio_path)
            return len(audio) / 1000.0
        except ImportError:
            cmd = [
                'ffprobe', '-v', 'quiet', '-show_entries', 'format=duration',
                '-of', 'default=noprint_wrappers=1:nokey=1', audio_path
            ]
            try:
                result = subprocess.run(cmd, capture_output=True, text=True, check=True)
                return float(result.stdout.strip())
            except:
                return 0.0


class VideoMerger:
    """视频合并器"""
    
    def __init__(self, ffmpeg_path: str = "ffmpeg"):
        self.ffmpeg_path = ffmpeg_path
    
    def _run_ffmpeg(self, args: List[str]) -> bool:
        """运行ffmpeg命令"""
        cmd = [self.ffmpeg_path] + args
        try:
            subprocess.run(cmd, check=True, capture_output=True)
            return True
        except subprocess.CalledProcessError as e:
            print(f"FFmpeg错误: {e.stderr.decode('utf-8', errors='ignore') if e.stderr else '未知错误'}")
            return False
    
    def concatenate_videos(self, video_list: List[str], output_path: str) -> bool:
        """拼接多个视频"""
        list_file = os.path.join(tempfile.gettempdir(), 'video_list.txt')
        with open(list_file, 'w', encoding='utf-8') as f:
            for video in video_list:
                escaped_path = video.replace('\\', '/')
                f.write(f"file '{escaped_path}'\n")
        
        args = [
            '-y',
            '-f', 'concat',
            '-safe', '0',
            '-i', list_file,
            '-c:v', 'libx264',
            '-c:a', 'aac',
            '-ar', '44100',
            '-ac', '1',  # 单声道
            '-pix_fmt', 'yuv420p',
            output_path
        ]
        
        result = self._run_ffmpeg(args)
        
        try:
            os.remove(list_file)
        except:
            pass
        
        return result


class SubtitleVideoCreator:
    """字幕视频创建器 - SRT文件版本"""
    
    def __init__(self, ffmpeg_path: str = "ffmpeg", temp_dir: Optional[str] = None):
        self.ffmpeg_path = ffmpeg_path
        self.temp_dir = temp_dir or tempfile.mkdtemp()
        
        self.video_processor = VideoProcessor(ffmpeg_path)
        self.tts_generator = TTSGenerator()
        self.merger = VideoMerger(ffmpeg_path)
    
    def _extract_last_frame(self, video_path: str, output_path: str) -> bool:
        """提取视频的最后一帧"""
        args = [
            self.ffmpeg_path,
            '-y',
            '-sseof', '-1',
            '-i', video_path,
            '-frames:v', '1',
            '-q:v', '2',
            output_path
        ]
        try:
            subprocess.run(args, capture_output=True, check=True)
            return True
        except:
            return False
    
    def _create_simple_paused_video(self, image_path: str, audio_path: str, output_path: str, duration: float, subtitle_text: str) -> bool:
        """创建暂停视频（静态画面 + TTS音频 + 字幕）"""
        safe_text = subtitle_text.replace('\\', '\\\\').replace("'", "\\'").replace('"', '\\"')
        
        args = [
            self.ffmpeg_path,
            '-y',
            '-loop', '1',
            '-framerate', '30',
            '-i', image_path,
            '-i', audio_path
        ]
        
        if subtitle_text:
            words = subtitle_text.split()
            lines = []
            current_line = ""
            
            for word in words:
                test_line = current_line + " " + word if current_line else word
                if len(test_line) <= 20:
                    current_line = test_line
                else:
                    if current_line:
                        lines.append(current_line)
                    current_line = word
            
            if current_line:
                lines.append(current_line)
            
            vf_filters = []
            for i, line in enumerate(lines):
                y_pos = 50 + i * 60
                safe_line = line.replace('\\', '\\\\').replace("'", "\\'").replace('"', '\\"')
                vf_filters.append(f"drawtext=text='{safe_line}':fontsize=50:fontcolor=red:box=0:bordercolor=green:borderw=2:x=(w-text_w)/2:y={y_pos}")
            
            if vf_filters:
                args.extend(['-vf', ','.join(vf_filters)])
        
        args.extend([
            '-c:v', 'libx264',
            '-c:a', 'aac',
            '-ar', '44100',
            '-ac', '1',  # 单声道
            '-t', str(duration),
            '-pix_fmt', 'yuv420p',
            output_path
        ])
        
        try:
            subprocess.run(args, check=True)
            return True
        except Exception as e:
            print(f"  简单暂停视频错误: {e}")
            try:
                simple_args = [
                    self.ffmpeg_path,
                    '-y',
                    '-loop', '1',
                    '-i', image_path,
                    '-i', audio_path,
                    '-c:v', 'libx264',
                    '-c:a', 'aac',
                    '-ar', '44100',
                    '-ac', '1',  # 单声道
                    '-t', str(duration),
                    '-pix_fmt', 'yuv420p',
                    output_path
                ]
                subprocess.run(simple_args, check=True)
                print(f"  不带字幕的版本创建成功")
                return True
            except:
                return False
    
    def _cleanup(self):
        """清理临时文件"""
        try:
            shutil.rmtree(self.temp_dir)
        except:
            pass
    
    def process(
        self,
        video_path: str,
        output_path: str,
        subtitle_path: str,
        lang: str = 'zh',
        pause_between: float = 0.8  # 句间停顿时间(秒)
    ) -> bool:
        """处理视频和字幕，生成最终视频
        
        Args:
            video_path: 输入视频路径
            output_path: 输出视频路径
            subtitle_path: 字幕文件路径
            lang: TTS语言 ('zh'为中文, 'en'为英文)
            pause_between: 句与句之间的停顿时间(秒)
        """
        print(f"开始处理...")
        print(f"视频: {video_path}")
        print(f"字幕: {subtitle_path}")
        
        if not os.path.exists(video_path):
            print(f"错误: 视频文件不存在: {video_path}")
            return False
        
        if not os.path.exists(subtitle_path):
            print(f"错误: 字幕文件不存在: {subtitle_path}")
            return False
        
        print("\n[1/4] 解析字幕...")
        subtitles = SubtitleParser.load_file(subtitle_path)
        print(f"找到 {len(subtitles)} 条字幕")
        
        if not subtitles:
            print("错误: 没有解析到字幕")
            return False
        
        print("\n[2/4] 处理字幕片段...")
        segment_videos = []
        
        subtitles = subtitles[:10]
        
        for i, sub in enumerate(subtitles):
            print(f"  处理第 {i+1}/{len(subtitles)} 条: {sub.text[:30]}...")
            
            video_segment = os.path.join(self.temp_dir, f"segment_{i:04d}_video.mp4")
            audio_file = os.path.join(self.temp_dir, f"segment_{i:04d}_audio.mp3")
            last_frame = os.path.join(self.temp_dir, f"segment_{i:04d}_last_frame.png")
            paused_video = os.path.join(self.temp_dir, f"segment_{i:04d}_paused.mp4")
            
            if not self.video_processor.cut_video_segment(
                video_path, sub.start_time, sub.end_time, video_segment
            ):
                print(f"  警告: 剪切视频片段失败，跳过此段")
                continue
            
            if not self.tts_generator.generate_audio(sub.text, audio_file, lang):
                print(f"  警告: 生成TTS音频失败，跳过此段")
                continue
            
            if not self._extract_last_frame(video_segment, last_frame):
                print(f"  警告: 提取最后一帧失败，跳过此段")
                continue
            
            audio_duration = self.tts_generator.get_audio_duration(audio_file)
            total_duration = audio_duration + pause_between  # 添加停顿时间
            print(f"  TTS音频时长: {audio_duration:.2f}秒, 总时长(含停顿): {total_duration:.2f}秒")
            
            if audio_duration > 0:
                if self._create_simple_paused_video(last_frame, audio_file, paused_video, total_duration, sub.text):
                    print(f"  暂停视频创建成功: {paused_video}")
                    segment_videos.append(video_segment)
                    segment_videos.append(paused_video)
                    print(f"  已添加片段: {len(segment_videos)}个")
                else:
                    print(f"  警告: 创建暂停视频失败，跳过此段")
                    continue
            else:
                print(f"  警告: TTS音频时长为0，跳过此段")
                continue
        
        if not segment_videos:
            print("错误: 没有成功生成任何视频片段")
            return False
        
        print("\n[3/4] 拼接所有片段...")
        if not self.merger.concatenate_videos(segment_videos, output_path):
            print("错误: 拼接视频失败")
            return False
        
        print("\n[4/4] 清理临时文件...")
        self._cleanup()
        
        print(f"\n完成! 输出文件: {output_path}")
        return True


def main():
    video_path = "睡觉是人生头等大事#健康#张雪峰_xWT111.mp4"
    subtitle_path = "output_en.srt"  # 使用英文字幕文件
    output_path = "output_en_final.mp4"  # 英文版本输出文件
    lang = "en"  # 使用英文TTS
    ffmpeg_path = "ffmpeg"
    
    creator = SubtitleVideoCreator(ffmpeg_path=ffmpeg_path)
    success = creator.process(
        video_path=video_path,
        output_path=output_path,
        subtitle_path=subtitle_path,
        lang=lang,
        pause_between=1.0  # 1秒停顿
    )
    
    return 0 if success else 1


if __name__ == '__main__':
    exit(main())