import datetime
import json
import logging
import os
import sys
import re
from datetime import datetime

# 确保能导入核心模块
from core.resolve_api import get_resolve
from config import get_data_cache_dir, get_lua_path, get_project_path

# 日志配置
from core.logger import get_logger

logger = get_logger('bgxiong_subtitle_reader')

def get_subtitle_list():
    """获取字幕列表（供前端显示）- 无参数版本"""
    resolve = get_resolve()
    try:
        if resolve is None:
            return {"success": False, "error": "无法连接 DaVinci Resolve", "items": []}
        
        result = get_subtitle_items(resolve)
        return result
    except Exception as e:
        logger.error(f"get_subtitle_list 异常: {e}")
        return {
            "success": False,
            "error": str(e),
            "items": []
        }

def get_timeline_info(): 
    resolve = get_resolve()
    """获取当前时间线的基本信息（名称、帧率、分辨率）"""
    try:
        if resolve is None:
            logger.debug("#get_timeline_info#: Resolve 对象为空")
            return {"success": False, "error": "Resolve 对象为空"}
        
        project_manager = resolve.GetProjectManager()
        if project_manager is None:
            logger.debug("#get_timeline_info#: 无法获取 ProjectManager")
            return {"success": False, "error": "无法获取 ProjectManager"}
        
        project = project_manager.GetCurrentProject()
        if project is None:
            logger.debug("#get_timeline_info#: 没有打开的项目")
            return {"success": False, "error": "没有打开的项目"}
        
        timeline = project.GetCurrentTimeline()
        if timeline is None:
            logger.debug("#get_timeline_info#: 没有打开的时间线")
            return {"success": False, "error": "没有打开的时间线"}
        
        timeline_name = timeline.GetName() or "未知时间线"
        
        start_frame = timeline.GetStartFrame()
        end_frame = timeline.GetEndFrame()
        timeline_duration_frames = end_frame - start_frame + 1
        fps = _safe_get_fps(project)

        videoTracks = timeline.GetTrackCount("video")
        audioTracks = timeline.GetTrackCount("audio")
        subtitleTracks = timeline.GetTrackCount("subtitle")

        # 起始时间吗
        start_timecode = timeline.GetStartTimecode()

        # 起始帧
        start_frame = timeline.GetStartFrame()
        # 结束帧
        end_frame = timeline.GetEndFrame()
                
        # 获取分辨率（部分版本支持）
        width, height = 0, 0
        get_width = getattr(timeline, 'GetSetting', None)
        get_height = getattr(timeline, 'GetSetting', None)
        if callable(get_width) and callable(get_height):
            try:
                width_str = get_width("timelineResolutionWidth")
                height_str = get_height("timelineResolutionHeight")
                width = int(width_str) if width_str else 0
                height = int(height_str) if height_str else 0
            except:
                pass

        data = {
            "duration": timeline_duration_frames,
            "name": timeline_name,
            "videoTracks": videoTracks,
            "audioTracks": audioTracks,
            "subtitleTracks": subtitleTracks,
            "start_timecode": start_timecode,
            "start_frame": start_frame,
            "end_frame": end_frame,
            "fps": fps,
            "resolution": f"{width}x{height}" if width and height else "未知分辨率"
            }
        
        return {
            "success": True,
            "data": data
        }
        
    except Exception as e:
        import traceback
        print(f"get_timeline_info 异常: {e}", file=sys.stderr)
        print(traceback.format_exc(), file=sys.stderr)
        return {"success": False, "error": str(e), "message": f"获取时间线信息失败：{str(e)}"}

def frames_to_timecode(frames, fps):
    """将帧数转换为 SRT 时间码格式 (HH:MM:SS,mmm)"""
    if fps <= 0:
        fps = 24
    total_seconds = frames / fps
    hours = int(total_seconds // 3600)
    minutes = int((total_seconds % 3600) // 60)
    seconds = int(total_seconds % 60)
    milliseconds = int((total_seconds % 1) * 1000)
    return f"{hours:02d}:{minutes:02d}:{seconds:02d},{milliseconds:03d}"


def frames_to_vtt_timecode(frames, fps):
    """将帧数转换为 VTT 时间码格式 (HH:MM:SS.mmm)"""
    if fps <= 0:
        fps = 24
    total_seconds = frames / fps
    hours = int(total_seconds // 3600)
    minutes = int((total_seconds % 3600) // 60)
    seconds = int(total_seconds % 60)
    milliseconds = int((total_seconds % 1) * 1000)
    return f"{hours:02d}:{minutes:02d}:{seconds:02d}.{milliseconds:03d}"


def get_subtitle_items(resolve):
    """
    获取当前时间线所有字幕项的完整信息
    【修复版】添加完整的 None 检查
    """
    try:
        # ⭐ 检查 resolve 对象
        if resolve is None:
            return {"success": False, "error": "Resolve 对象为空", "items": []}
        
        # ⭐ 安全检查 GetProjectManager
        get_pm = getattr(resolve, 'GetProjectManager', None)
        if not callable(get_pm):
            return {"success": False, "error": "Resolve.GetProjectManager 不可用", "items": []}
        
        project_manager = get_pm()
        if project_manager is None:
            return {"success": False, "error": "无法获取 ProjectManager", "items": []}
        
        # ⭐ 安全检查 GetCurrentProject
        get_cp = getattr(project_manager, 'GetCurrentProject', None)
        if not callable(get_cp):
            return {"success": False, "error": "ProjectManager.GetCurrentProject 不可用", "items": []}
        
        project = get_cp()
        if project is None:
            return {"success": False, "error": "没有打开的项目", "items": []}
        
        # ⭐ 安全检查 GetCurrentTimeline
        get_ct = getattr(project, 'GetCurrentTimeline', None)
        if not callable(get_ct):
            return {"success": False, "error": "Project.GetCurrentTimeline 不可用", "items": []}
        
        timeline = get_ct()
        if timeline is None:
            return {"success": False, "error": "没有打开的时间线", "items": []}
        
        # ⭐ 安全检查 GetTrackCount
        get_tc = getattr(timeline, 'GetTrackCount', None)
        if not callable(get_tc):
            return {"success": False, "error": "Timeline.GetTrackCount 不可用", "items": []}
        
        # 获取字幕轨道数量
        subtitle_track_count = get_tc("subtitle")
        
        logger.debug(f"字幕轨道数量: {subtitle_track_count}")

        if subtitle_track_count == 0:
            return {"success": True, "items": [], "message": "没有字幕轨道"}
        
        all_items = []
        
        # 遍历每个字幕轨道
        for track_index in range(1, subtitle_track_count + 1):
            isenabled = timeline.GetIsTrackEnabled("subtitle", track_index)
            if(not isenabled):
                logger.debug(f"字幕轨道 {track_index} 被禁用！！！")
                continue
            # ⭐ 安全检查 GetItemListInTrack
            get_it = getattr(timeline, 'GetItemListInTrack', None)
            if not callable(get_it):
                continue
            # 这里返回所有字幕片段
            clips = get_it("subtitle", track_index)
            if not clips:
                continue
            logger.debug(f"轨道 {track_index} 字幕项数量: {len(clips)}")          
            for clip in clips:
                
                try:
                    # ⭐ 安全检查 clip 对象方法
                    clip_get_name = getattr(clip, 'GetName', None)
                    clip_get_start = getattr(clip, 'GetStart', None)
                    clip_get_end = getattr(clip, 'GetEnd', None)
                    clip_get_duration = getattr(clip, 'GetDuration', None)
                    clip_get_subtitle = getattr(clip, 'GetSubtitle', None)
                    clip_get_font_name = getattr(clip, 'GetFontName', None)
                    clip_get_font_size = getattr(clip, 'GetFontSize', None)
                    clip_get_color = getattr(clip, 'GetColor', None)

                    # logger.debug(f"处理字幕项: {clip_get_name() if callable(clip_get_name) else '未知'}")
                    # logger.debug(f"方法可用性 - GetName: {callable(clip_get_name)}, GetStart: {callable(clip_get_start)}, "
                    #              f"GetEnd: {callable(clip_get_end)}, GetDuration: {callable(clip_get_duration)}, "
                    #              f"GetSubtitle: {callable(clip_get_subtitle)}, GetFontName: {callable(clip_get_font_name)}, GetFontSize: {callable(clip_get_font_size)}, GetColor: {callable(clip_get_color)}"
                    #              ) 
                    
                    if not callable(clip_get_name) or clip_get_name() is None:
                        continue
                    
                    # 读取字幕内容
                    item_data = {
                        "track_index": track_index,
                        "clip_name": clip_get_name() or "",
                        "start_frame": clip_get_start() or 0,
                        "end_frame": clip_get_end() or 0,
                        "duration_frame": clip_get_duration() or 0,
                        "start_tc": "",
                        "end_tc": "",
                        "text": clip_get_name() or "",
                    }

                    # 计算时间码（需要帧率）
                    fps = _safe_get_fps(project)
                    item_data["start_tc"] = frames_to_timecode(item_data["start_frame"], fps)
                    item_data["end_tc"] = frames_to_timecode(item_data["end_frame"], fps)

                    # 获取字幕颜色
                    if callable(clip_get_color):
                        try:
                            color = clip_get_color()
                            if color and isinstance(color, dict):
                                item_data["color"] = {
                                    "r": int(color.get("r", 1) * 255),
                                    "g": int(color.get("g", 1) * 255),
                                    "b": int(color.get("b", 1) * 255),
                                    "a": int(color.get("a", 1) * 255)
                                }
                        except:
                            pass
                    all_items.append(item_data)
                except Exception as item_err:
                    logger.error(f"读取字幕项错误：{item_err}")
                    continue
                # 按开始时间排序
                all_items.sort(key=lambda x: x["start_frame"])
        return {
            "success": True,
            "items": all_items,
            "track_count": subtitle_track_count,
            "item_count": len(all_items),
            "message": f"成功读取 {len(all_items)} 个字幕项"
        }
        
    except Exception as e:
        logger.error(f"get_subtitle_items 异常: {e}")
        return {
            "success": False,
            "error": str(e),
            "items": [],
            "message": f"读取字幕失败：{str(e)}"
        }


def _safe_get_fps(project):
    """安全获取项目帧率"""
    try:
        # 尝试方法 1: GetSettingObject
        get_setting_obj = getattr(project, 'GetSettingObject', None)
        if callable(get_setting_obj):
            settings = get_setting_obj()
            if settings:
                get_setting = getattr(settings, 'GetSetting', None)
                if callable(get_setting):
                    fps_str = get_setting("timelineFrameRate")
                    if fps_str:
                        return float(fps_str)
        
        # 尝试方法 2: 直接 GetSetting (部分 Resolve 版本支持)
        get_setting_direct = getattr(project, 'GetSetting', None)
        if callable(get_setting_direct):
            fps_str = get_setting_direct("timelineFrameRate")
            if fps_str:
                return float(fps_str)
        
    except:
        pass
    
    # 默认值
    return 24.0


def create_subtitles(payload_str):
    """根据前端传来的字幕数据创建字幕"""
    try:
        import json
        subtitle_data = json.loads(payload_str)
        _language = subtitle_data.get("language", "auto")
        _subtitle_line_chars = subtitle_data.get("chars", 38)
        # 这里可以添加对 subtitle_data 的验证
        logger.debug(f"创建字幕 - 语言: {_language}, 字数/行: {_subtitle_line_chars}, 数据: {subtitle_data}")    
        resolve = get_resolve()
        if resolve is None:
            return {"success": False, "error": "无法连接 DaVinci Resolve"}
        # 获取时间线名称
        if(_language == "auto"):
           language = resolve.AUTO_CAPTION_AUTO
        elif(_language == "zh"):
            language = resolve.AUTO_CAPTION_MANDARIN_SIMPLIFIED
        elif(_language == "zh-TW"):
            language = resolve.AUTO_CAPTION_MANDARIN_TRADITIONAL
        elif(_language == "en"):
            language = resolve.AUTO_CAPTION_ENGLISH
        settings = {
            resolve.SUBTITLE_LANGUAGE: language,
            resolve.SUBTITLE_CHARS_PER_LINE: _subtitle_line_chars,
            resolve.GAP: 5,
            resolve.SUBTITLE_LINE_BREAK: resolve.AUTO_CAPTION_LINE_SINGLE,
            resolve.SUBTITLE_CAPTION_PRESET: resolve.AUTO_CAPTION_PRESET_DEFAULT
        }
        logger.debug(f"字幕生成设置: {settings}")
        project_manager = resolve.GetProjectManager()
        project = project_manager.GetCurrentProject()
        timeline = project.GetCurrentTimeline()
        timeline.CreateSubtitlesFromAudio(settings)
        return {"success": True, "message": "字幕创建成功（示例返回）"}
    except Exception as e:
        logger.error(f"create_subtitles 异常: {e}")
        return {"success": False, "error": str(e), "message": f"创建字幕失败：{str(e)}"}    


def export_current_timeline_subtitles():
    """导出当前时间线字幕（使用手动读取方式）"""
    try:
        resolve = get_resolve()
        if resolve is None:
            return {"success": False, "error": "无法连接 DaVinci Resolve"}
        
        # 获取时间线名称
        project_manager = resolve.GetProjectManager()
        project = project_manager.GetCurrentProject()
        timeline = project.GetCurrentTimeline()
        
        if not timeline:
            return {"success": False, "error": "没有打开的时间线"}
        
        timeline_name = timeline.GetName()
        safe_timeline_name = re.sub(r'[\\/*?:"<>|]', "_", timeline_name)[:50]
        
        # 构建导出目录
        subtitles_dir = os.path.join(DATA_CACHE_DIR, 'subtitles')
        if not os.path.exists(subtitles_dir):
            os.makedirs(subtitles_dir, exist_ok=True)
        
        # 导出为 SRT（推荐格式）
        output_path = os.path.join(subtitles_dir, f"{safe_timeline_name}.srt")
        result = export_subtitles_to_srt(resolve, output_path)
        
        return result
        
    except Exception as e:
        logger.error(f"export_current_timeline_subtitles 异常: {e}")
        return {"success": False, "error": str(e), "message": f"导出字幕失败：{str(e)}"}


def export_subtitles_to_srt(resolve, output_path):
    """将字幕导出为标准 SRT 格式"""
    try:
        result = get_subtitle_items(resolve)
        if not result["success"]:
            return result
        
        items = result["items"]
        if not items:
            return {"success": False, "error": "没有字幕内容可导出"}
        
        # 构建 SRT 内容
        srt_content = ""
        for index, item in enumerate(items, 1):
            srt_content += f"{index}\n"
            srt_content += f"{item['start_tc']} --> {item['end_tc']}\n"
            srt_content += f"{item['text']}\n\n"
        
        # 确保目录存在
        output_dir = os.path.dirname(output_path)
        if output_dir and not os.path.exists(output_dir):
            os.makedirs(output_dir, exist_ok=True)
        
        # 以 UTF-8 写入（带 BOM，兼容 Excel 和编辑器）
        with open(output_path, 'w', encoding='utf-8-sig', newline='\n') as f:
            f.write(srt_content)
        
        return {
            "success": True,
            "output_path": output_path.replace('\\', '/'),
            "item_count": len(items),
            "message": f"成功导出 {len(items)} 条字幕到 {output_path}"
        }
        
    except Exception as e:
        return {"success": False, "error": str(e), "message": f"导出 SRT 失败：{str(e)}"}

def import_subtitles_from_srt(srt_path):
    """
    从 SRT 文件导入字幕到当前时间线 (通过调用 Lua 脚本)
    策略：Python -> RunScript Lua -> Lua 执行全部导入逻辑 -> Python 返回结果
    """
    try:
        logger.debug(f"🔄 通过 Lua 脚本导入 SRT: {srt_path}")

        # 验证文件存在
        if not os.path.exists(srt_path):
            logger.error(f"❌ SRT 文件不存在：{srt_path}")
            return {"success": False, "error": f"文件不存在：{srt_path}"}

        # 1. 获取 Resolve 对象
        resolve = get_resolve()
        project_manager = resolve.GetProjectManager()
        project = project_manager.GetCurrentProject()
        timeline = project.GetCurrentTimeline()
        media_pool = project.GetMediaPool()
        root_folder = media_pool.GetRootFolder()
        if resolve is None:
            return {"success": False, "error": "无法连接 DaVinci Resolve"}

        # 2. 【关键】调用 Lua 脚本
        # Lua 脚本的路径 (需要根据你的项目结构调整)
        lua_script_path = os.path.join(get_lua_path(), "subtitles.lua")

        if not os.path.exists(lua_script_path):
            logger.error(f"❌ Lua 脚本不存在：{lua_script_path}")
            return {"success": False, "error": f"Lua 脚本不存在：{lua_script_path}"}

        logger.debug(f"🔄 调用 Lua 脚本: {lua_script_path}，参数: {srt_path}")

        # 获取 Fusion 对象并运行脚本
        fusion = resolve.Fusion()
        if not fusion:
            logger.error("❌ 无法获取 Fusion 对象")
            return {"success": False, "error": "无法获取 Fusion 对象"}
        
        safe_lua_script_path = os.path.normpath(lua_script_path).replace('\\', '/')
        safe_srt_path_for_lua = os.path.normpath(srt_path).replace('\\', '/') # 重命名变量以明确用途
        # RunScript 会执行 Lua 脚本，并返回脚本 print 的内容
        # 我们将 SRT 路径作为参数传递给 Lua 脚本
        lua_code_with_args = f'''
        -- 传递给 Lua 脚本的参数
        local srtFilePath = "{safe_srt_path_for_lua}"
        -- 加载并执行主逻辑
        dofile("{safe_lua_script_path}")
        -- 调用处理函数
        local success, details = importSubtitleFromPath(srtFilePath)
        if success then
            print("SUCCESS:" .. details)
        else
            print("ERROR:" .. details)
        end
        '''
        fusion.Execute(lua_code_with_args)
        return {
            "success": True,
            "message": "字幕保存成功"
        }
    except Exception as e:
        logger.error(f"❌ 调用 Lua 脚本导入字幕时发生异常：{e}", exc_info=True)
        import traceback
        logger.error(traceback.format_exc())
        return {"success": False, "error": str(e), "message": f"调用 Lua 脚本失败：{str(e)}"}

def save_subtitle_changes(payload_str):
    # 达芬奇不支持字幕修
    return False

def get_rules_config_path():
    _rules_dir = get_data_cache_dir()
    _rules_filename = "subtitls_rules.json"
    _rules_filepath = os.path.join(_rules_dir, _rules_filename)
    logger.debug("保存规则配置文件：" + _rules_filepath)
    return _rules_filepath


def subtitle_save_replace_rules(rules):
    """
    保存替换规则到 JSON 文件（直接覆盖，不验证数据）
    @param rules: 规则数组（list）或 JSON 字符串（str）
    """
    try:
        # ⭐ 如果传入的是字符串，尝试解析为列表
        if isinstance(rules, str):
            # 清理可能的空白字符
            rules = rules.strip()
            if not rules:
                rules = []
            else:
                rules = json.loads(rules)
        config_path = get_rules_config_path()
        logger.debug("字幕规则文件存放地址：" + config_path)
        with open(config_path, 'w', encoding='utf-8') as f:
            json.dump(rules, f, ensure_ascii=False, indent=2)
        logger.info(f"✓ 替换规则已保存：{config_path} (共 {len(rules)} 条)")
        return {
            "success": True,
            "message": f"已保存 {len(rules)} 条替换规则",
            "path": config_path.replace('\\', '/'),
            "count": len(rules)
        }
    except Exception as e:
        logger.error(f"保存规则失败：{e}")
        import traceback
        logger.error(traceback.format_exc())
        return {
            "success": False,
            "error": f"保存失败：{str(e)}"
        }

def subtitle_load_replace_rules():
    """
    从 JSON 文件加载替换规则
    @return: JSON 字符串格式的规则数组
    """
    try:
        # 1. 获取配置文件路径
        config_path = get_rules_config_path()
        
        # 2. 检查文件是否存在
        if not os.path.exists(config_path):
            logger.debug(f"规则配置文件不存在：{config_path}")
            return {
                "success": True,  # ⭐ 注意：文件不存在不算错误，返回空数组
                "rules": [],
                "message": "没有找到已保存的规则"
            }
        
        # 3. 读取 JSON 文件
        with open(config_path, 'r', encoding='utf-8') as f:
            rules = json.load(f)
        
        # 4. 验证数据格式
        if not isinstance(rules, list):
            logger.warning(f"规则文件格式错误，重置为空数组：{config_path}")
            rules = []
        
        logger.info(f"✓ 已加载替换规则：{config_path} (共 {len(rules)} 条)")
        
        return {
            "success": True,
            "rules": rules,
            "count": len(rules),
            "path": config_path.replace('\\', '/')
        }
    except Exception as e:
        logger.error(f"加载规则失败：{e}")
        import traceback
        logger.error(traceback.format_exc())
        return {
            "success": False,
            "error": f"加载失败：{str(e)}",
            "rules": []
        }