import docx
from moviepy.editor import VideoFileClip
import time
import concurrent.futures
import re
import google.generativeai as genai
import os
from openai import OpenAI
from pydub import AudioSegment
from typing import List, Dict

# 设置 FFmpeg 路径
ffmpeg_path = r"D:\ffmpeg-master-latest-win64-gpl-shared\bin"  # 替换为您的实际路径
os.environ["PATH"] += os.pathsep + ffmpeg_path
AudioSegment.converter = os.path.join(ffmpeg_path, "ffmpeg.exe")

# 设置 API 配置（使用 Ifasr.py 中的配置）
DEFAULT_API_BASE = "https://jeniya.cn/v1"
DEFAULT_API_KEY = "sk-5w2FNpdHmV4xoi07RAe2lWiqXGgvRWCbmCk9o8T39hZBhJIc"

# DEFAULT_API_BASE = "https://api.chatfire.cn/v1"
# DEFAULT_API_KEY = "sk-QwXT3QeorfDPerfxs2Q76i9yDoKvOOG90Q135BNKtYXB3yE2"

LLM_cnt = 1




def compress_audio(input_file, output_file, bitrate="64k"):
    """压缩音频文件以减小大小"""
    try:
        # 检查输入文件是否存在
        if not os.path.exists(input_file):
            print(f"压缩音频错误: 输入文件不存在 - {input_file}")
            return False
        
        print(f"   正在压缩: {os.path.basename(input_file)} (比特率: {bitrate})")
        
        # 尝试自动查找 ffmpeg（优先使用系统PATH中的）
        try:
            audio = AudioSegment.from_file(input_file)
        except FileNotFoundError as e:
            # 如果找不到 ffmpeg，尝试设置路径
            print(f"   ⚠️  FFmpeg未找到，尝试设置路径...")
            possible_paths = [
                r"D:\ffmpeg-master-latest-win64-gpl-shared\bin",
                r"C:\ffmpeg\bin",
                r"C:\Program Files\ffmpeg\bin",
            ]
            
            ffmpeg_found = False
            for path in possible_paths:
                if os.path.exists(path):
                    os.environ["PATH"] += os.pathsep + path
                    AudioSegment.converter = os.path.join(path, "ffmpeg.exe")
                    print(f"   ✅ 找到FFmpeg: {path}")
                    ffmpeg_found = True
                    break
            
            if not ffmpeg_found:
                print(f"   ❌ 找不到FFmpeg，请安装FFmpeg或设置PATH环境变量")
                print(f"   💡 下载: https://ffmpeg.org/download.html")
                return False
            
            # 重试
            audio = AudioSegment.from_file(input_file)
        
        # 降低比特率以减小文件大小
        audio.export(output_file, format="mp3", bitrate=bitrate)
        
        # 显示压缩结果
        input_size = os.path.getsize(input_file) / (1024 * 1024)
        output_size = os.path.getsize(output_file) / (1024 * 1024)
        compression_ratio = (1 - output_size / input_size) * 100
        
        print(f"   ✅ 压缩完成: {input_size:.2f}MB → {output_size:.2f}MB (节省 {compression_ratio:.1f}%)")
        return True
        
    except Exception as e:
        print(f"   ❌ 压缩音频错误: {e}")
        import traceback
        traceback.print_exc()
        return False


def format_transfer(input_file, output_file):
    """将视频文件转换为音频文件"""
    video = VideoFileClip(input_file)
    video.audio.write_audiofile(output_file)
    video.close()


def extract_time_coded_content(file_path):
    """从Word文档中提取时间编码内容"""
    doc = docx.Document(file_path)
    full_text = '\n'.join([para.text for para in doc.paragraphs])
    lines = full_text.split('\n')

    time_coded_content = {}
    current_time_code = None
    current_content = []

    for line in lines:
        if line.startswith('发言人') and ' ' in line:
            if current_time_code:
                time_coded_content[current_time_code] = ' '.join(current_content).strip()
                current_content = []

            time_code = line.split()[1]
            current_time_code = time_code
        elif current_time_code:
            current_content.append(line)

    if current_time_code:
        time_coded_content[current_time_code] = ' '.join(current_content).strip()

    formatted_output = []
    time_codes = sorted(list(time_coded_content.keys()))
    for i in range(len(time_codes) - 1):
        start_time = time_codes[i]
        end_time = time_codes[i + 1]
        content = time_coded_content[start_time]
        formatted_output.append(f"{start_time}-{end_time}: {content}")

    return formatted_output


def extract_timestamp_conversation(file_path):
    """从Word文档中提取时间戳对话并保存为文本文件"""
    output_file_path = file_path.replace('_原文.docx', '.txt')
    try:
        results = extract_time_coded_content(file_path)

        with open(output_file_path, 'w', encoding='utf-8') as f:
            for result in results:
                time_range, content = result.split(': ', 1)
                f.write(f'"{time_range}": "{content}"\n')

        print(f"结果已写入 {output_file_path}")

    except Exception as e:
        print(f"发生错误: {e}")


def get_filenames_recursive(directory, dataType):
    """递归获取目录中指定类型的文件"""
    files = []
    for root, _, filenames in os.walk(directory):
        for filename in filenames:
            if filename.endswith(dataType):
                files.append(os.path.join(root, filename))
    return files


def process_file(mp4_path):
    """处理单个视频文件转换为音频"""
    file_prefix = os.path.splitext(os.path.basename(mp4_path))[0]
    output_dir = os.path.dirname(mp4_path)
    output_path = os.path.join(output_dir, f"{file_prefix}.mp3")

    counter = 1
    while os.path.exists(output_path):
        output_path = os.path.join(output_dir, f"{file_prefix}_{counter}.mp3")
        counter += 1

    print(f"转换 {mp4_path} 到 {output_path}")
    format_transfer(mp4_path, output_path)
    return output_path


def transcribe_audio_with_whisper(
    mp3_file: str, 
    api_base: str = None,
    api_key: str = None
) -> Dict:
    """
    使用Whisper API进行音频转录（基于 Ifasr.py 的新版实现）
    
    Args:
        mp3_file: 音频文件路径
        api_base: API提供商地址（默认: https://jeniya.cn/v1）
        api_key: API密钥
    
    Returns:
        Dict: 转录结果
    """
    try:
        # 使用默认配置或传入的配置
        if api_base is None:
            api_base = DEFAULT_API_BASE
        if api_key is None:
            api_key = DEFAULT_API_KEY
        
        print(f"🔊 使用 Whisper API: {api_base}")
        
        # 创建 OpenAI 客户端（基于 Ifasr.py 的方式）
        api_base = "https://jeniya.cn/v1"
        api_key = "sk-OuApxqfz6dPlVE61mOll5wk6YymayOdZlIJqdrfzDRyypxvS"
        client = OpenAI(
            base_url=api_base,
            api_key=api_key
        )
        print(api_base)
        
        audio_file_path = mp3_file
        print(f"   📁 音频文件: {os.path.basename(mp3_file)}")
        
        audio_file =  open(audio_file_path, "rb") 
            # 使用新的 API 调用方式（参考 Ifasr.py）
        print("   🔄 调用 Whisper 进行转录...")
        transcription = client.audio.transcriptions.create(
        file=audio_file,
        model="whisper-1",
        response_format="verbose_json"
        )

        # 清理临时文件
        if audio_file_path != mp3_file and os.path.exists(audio_file_path):
            os.remove(audio_file_path)

        return transcription

    except Exception as e:
        print(f"   ❌ Whisper API 错误: {e}")
        import traceback
        traceback.print_exc()
        return None


def process_whisper_transcription(mp3_file: str) -> str:
    """处理Whisper转录结果，生成格式化的文本文件"""
    try:
        transcript = transcribe_audio_with_whisper(mp3_file)
        if not transcript:
            print("API转录失败，尝试使用备用方案...")
            return None

        # 生成输出文件路径
        output_file = mp3_file.replace('.mp3', '_whisper.txt')

        with open(output_file, 'w', encoding='utf-8') as f:
            # 写入完整的转录文本

            # 检查是否有segments字段
            if hasattr(transcript, 'segments') and transcript.segments:
                # 处理每个时间戳分段
                for segment in transcript.segments:
                    start_time = segment.get('start', 0)
                    end_time = segment.get('end', 0)
                    text = segment.get('text', '').strip()

                    # 转换时间为分钟:秒格式
                    start_min = int(start_time // 60)
                    start_sec = int(start_time % 60)
                    end_min = int(end_time // 60)
                    end_sec = int(end_time % 60)

                    time_range = f"{start_min:02d}:{start_sec:02d}-{end_min:02d}:{end_sec:02d}"
                    f.write(f'"{time_range}": "{text}"\n')
            else:
                # 如果没有segments，只写入完整文本
                f.write("未获取到时间戳分段信息\n")

        print(f"Whisper转录结果已保存到: {output_file}")
        return output_file

    except Exception as e:
        print(f"处理Whisper转录结果错误: {e}")
        return None


def parse_timestamps(text_file):
    """解析时间戳文件"""
    timestamps = {}

    with open(text_file, 'r', encoding='utf-8') as f:
        content = f.read()

    pattern = r'"(\d{2}:\d{2}-\d{2}:\d{2})"\s*:\s*"([^"]*)"'
    matches = re.findall(pattern, content)

    for timestamp, description in matches:
        def time_to_seconds(time_str):
            mins, secs = map(int, time_str.split(':'))
            return mins * 60 + secs

        start, end = timestamp.split('-')
        start_sec = time_to_seconds(start)
        end_sec = time_to_seconds(end)

        key = f"clip_{start.replace(':', '_')}"
        timestamps[key] = (start_sec, end_sec, description)

    return timestamps


def trim_video(input_video, output_video, timestamps) -> None:
    """根据时间戳剪辑视频"""
    from moviepy import VideoFileClip

    video = VideoFileClip(input_video)

    input_folder_name = os.path.basename(os.path.dirname(input_video))
    output_folder = os.path.join(os.path.dirname(input_video), input_folder_name)

    os.makedirs(output_folder, exist_ok=True)

    for clip_name, (start, end, content) in timestamps.items():
        try:
            # 使用正确的 subclip 方法
            clip = video.subclip(start, end)

            safe_content = ''.join(c for c in content[:20] if '\u4e00' <= c <= '\u9fff') or "content"
            output_filename = os.path.join(output_folder, f"{clip_name}_{safe_content}.mp4")

            clip.write_videofile(
                output_filename,
                codec='libx264',
                audio_codec='aac',
                verbose=False,  # 减少输出信息
                logger=None  # 禁用日志
            )

            print(f"剪辑完成 {clip_name}: {start}s - {end}s")

            # 显式关闭剪辑
            clip.close()

        except Exception as e:
            print(f"剪辑失败 {clip_name}: {e}")

    # 显式关闭视频
    video.close()


def clipVideo(video) -> None:
    """剪辑视频主函数"""
    input_file = video

    # 查找对应的文本文件
    video_dir = os.path.dirname(input_file)
    base_name = os.path.basename(video).replace('.mp4', '').strip()

    # 查找所有可能的文本文件
    possible_files = [
        f"{base_name}.txt",
        f"{base_name}_whisper.txt",
        f"{base_name}_.txt"
    ]

    text_file = None
    for file in possible_files:
        file_path = os.path.join(video_dir, file)
        if os.path.exists(file_path):
            text_file = file_path
            break

    if not text_file:
        # 尝试模糊匹配
        txt_files = get_filenames_recursive(video_dir, '.txt')
        for file in txt_files:
            if base_name in os.path.basename(file):
                text_file = file
                break

    if not text_file:
        print(f"未找到对应的文本文件: {base_name}")
        return

    print(f"使用文本文件: {text_file}")
    timestamps = parse_timestamps(text_file)

    if timestamps:
        trim_video(input_file, input_file.replace('.mp4', ''), timestamps)
    else:
        print("未找到有效的时间戳")


import requests
import json


def LLM_SemanticIntegration(filepath: list) -> str:
    """
    使用 Qwen3-8B 模型进行语义整合（通过 API 调用）
    """
    # 您的 API 密钥
    API_KEY = "sk-bjfqfkwhnuspbcjatrvsqbiqfmerhxnxhyjybwymirxsomgs"

    # 读取所有文本文件内容
    combined_content = ""
    for file in filepath:
        try:
            with open(file, 'r', encoding='utf-8') as f:
                combined_content += f.read() + "\n\n"
        except Exception as e:
            print(f"读取文件 {file} 失败: {e}")
            continue

    # 限制内容长度，避免超过 token 限制
    if len(combined_content) > 10000:
        combined_content = combined_content[:10000] + "...[内容过长已截断]"

    # 构造提示词
    prompt = f"""请将下面的音频转录内容按照语义重新分段，保持原始内容不变，只调整时间戳的分段。

输出格式要求：每行格式为"开始时间-结束时间": "原文内容"
注意：不要修改原文内容，只负责按照语义逻辑重新划分时间分段。

转录内容：
{combined_content}"""

    try:
        # 使用 ChatfireAPI 替代 Qwen3-8B
        # 通过 OpenAI 兼容接口调用
        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",  # 使用 Chatfire 支持的模型
            messages=[
                {
                    "role": "system",
                    "content": "你是一个专业的文本处理助手，擅长对音频转录内容进行语义分析和分段。"
                },
                {
                    "role": "user",
                    "content": prompt
                }
            ],
            max_tokens=4000,
            temperature=0.3
        )

        return response.choices[0].message.content

    except Exception as e:
        print(f"调用 API 时出错: {e}")
        # 备用方案：直接返回原始内容，不进行语义整合
        print("使用备用方案：跳过语义整合步骤")
        return None


def remove_blank_lines_from_txt(file_path: str) -> None:
    """移除文本文件中的空白行"""
    try:
        with open(file_path, 'r', encoding='utf-8') as file:
            lines = file.readlines()

        with open(file_path, 'w', encoding='utf-8') as file:
            for line in lines:
                if line.strip():  # 仅写入非空白行
                    file.write(line)

        print(f"已清理空白行: {file_path}")

    except Exception as e:
        print(f"清理空白行错误: {e}")


def batch_transcribe_audio(directory: str) -> List[str]:
    """批量转录目录中的所有MP3文件"""
    mp3_files = get_filenames_recursive(directory, '.mp3')
    transcribed_files = []

    print(f"找到 {len(mp3_files)} 个MP3文件进行转录...")

    for mp3_file in mp3_files:
        print(f"正在转录: {mp3_file}")
        result_file = process_whisper_transcription(mp3_file)
        if result_file:
            transcribed_files.append(result_file)
        # 添加延迟以避免API限制
        time.sleep(2)  # 增加延迟时间

    return transcribed_files


if __name__ == "__main__":
    # 定义要处理的目录
    url_list = [r"D:\lu_work\25年\lu10.24\图谱自动化构建"]

    # 1. 将视频转换为音频
    for item in url_list:
        mp4_files = get_filenames_recursive(item, '.mp4')
        print(f"找到 {len(mp4_files)} 个MP4文件进行转换...")
        with concurrent.futures.ThreadPoolExecutor() as executor:
            executor.map(process_file, mp4_files)

    # 2. 使用ChatfireAPI的Whisper服务转录音频
    print("开始使用ChatfireAPI Whisper服务转录音频...")
    for item in url_list:
        transcribed_files = batch_transcribe_audio(item)
        print(f"转录完成，生成 {len(transcribed_files)} 个文本文件")

    # 3. 音频转文本(Whisper) -> 重新分段(使用ChatfireAPI)
    for item in url_list:
        # 获取Whisper生成的文本文件
        txt_files = get_filenames_recursive(item, '_whisper.txt')
        if not txt_files:
            # 如果没有Whisper文件，回退到原来的Word文档处理
            print("未找到Whisper转录文件，尝试使用Word文档...")
            docx_files = get_filenames_recursive(item, '.docx')
            target_docx_files = [f for f in docx_files if f.endswith('_原文.docx')]

            with concurrent.futures.ThreadPoolExecutor() as executor:
                executor.map(extract_timestamp_conversation, target_docx_files)
            txt_files = get_filenames_recursive(item, '.txt')
        else:
            # 重命名Whisper文件以符合后续处理格式
            for txt_file in txt_files:
                new_name = txt_file.replace('_whisper.txt', '.txt')
                os.rename(txt_file, new_name)
                print(f"重命名: {txt_file} -> {new_name}")
            txt_files = [f.replace('_whisper.txt', '.txt') for f in txt_files]

        # 使用ChatfireAPI进行语义整合（如果失败则跳过）
        if txt_files:
            print("开始语义整合...")
            content = LLM_SemanticIntegration(txt_files)
            if content:
                # 保存语义整合结果
                output_file = os.path.join(item, "semantic_integration.txt")
                with open(output_file, 'w', encoding='utf-8') as f:
                    f.write(content)
                print(f"语义整合结果已保存到: {output_file}")
            else:
                print("语义整合失败，继续使用原始分段")
        else:
            print("未找到文本文件进行语义整合")

    # 清理空白行
    for item in url_list:
        txt_files = get_filenames_recursive(item, '.txt')
        target_files = [f for f in txt_files if f.endswith('_.txt')]
        print(f"清理 {len(target_files)} 个文件的空行")
        for file in target_files:
            remove_blank_lines_from_txt(file)

    # 4. 根据时间戳剪辑视频
    for item in url_list:
        videos = get_filenames_recursive(item, '.mp4')
        target_videos = [f for f in videos if "clip_" not in f]  # 排除已剪辑的视频
        print(f"找到 {len(target_videos)} 个视频文件进行剪辑...")
        # 使用串行处理以避免并发问题
        for video in target_videos:
            clipVideo(video)

    print("所有处理完成!")